默认情况下 驱动程序会将所有的请求路由到主节点 这通常也是你需要的 但是也可以通过设置驱动程序的读取首选项(read preferences)配置其他选项 可以在读选项中设置需要将查询路由到的服务器的类型
虽然将读请求路由到到备份节点不是一个好主意 但是在特定的情况下这是有意义的 如果你正在考虑将读请求发送到备份节点 请先从下面几个方面好好权衡
- 考虑一致性 对于一致性要求非常高的应用程序 不应该从备份节点读取数据 通常来说 备份节点的数据只会比主节点 落后几号秒 ,但是由于加载问题 配置错误 网络故障等原因 落后几分钟几个小时 几天也是有可能 但是客户端并不知道备份节点的数据有多新鲜 读取一个远远落后于主节点的数据 客户端不会觉得有任务问题 至于这些数据 是不是有问题这就需要你自己根据业务来判断了 如果应用程序需要读取他自己的写操作 那么就不要把读请求发给备份节点 后果自己想.因为客户端发送请求的速度可能会不备份节点复制操作要快 为了能够始终将写请求和读请求发给主节点 许多将读选项设置为Primary 默认就是这个选项 如果没有主节点 查询会出错误
- 考虑负载均衡 许多用户将请求发给备份节点 以便实现分布式的负载均衡 例如如果你的服务器每秒只能处理1000次查询 而你需要每秒3000次的查询 那么就需要设置几个备份节点 来分担一些数据加载的工作 这种做法很危险 容易系统意外过载 一旦出现这种情况 很难恢复 假如你遇到了上述情况 你决定创建拥有4个成员的副本集 每个备份节点的压力都在可承受范围内 整个系统也在正常运转 后来其中一个备份节点崩溃了.那么剩余的每个成员的负载都是100 如果需要恢复刚刚崩溃的成员 那么就需要从其他成员处复制数据 这个崩溃的成员换选择一个同步源 这样 这个作为同步源的成员的要过载 服务器过载晋朝导致新能变慢,副本集性能进一步降底 然后强制其他成员承担过多的负载 导致这些成员变得更慢 这是一个恶心循环, 如果能明确知道每台服务器能够承受的负载,你可能会觉得自己能够更好地因对这种情况 使用五台 而不是4台 这样即使1台崩溃 也不会过载 即使这样你也要处理其他服务器负载过大的情况 一个更好地选择就是用分片做分布式负载
读偏好(Read Preference)
读偏好描述了MongoDB客户端如何将读请求路由到副本集的成员。
默认情况下,一个应用会将其读操作导向副本集中的primary。从primary中读可以保证读操作返回的是最新的文档。如果一个应用不需要完全实时的数据,则可以通过分布一些或全部的读操作到副本集的secondary成员上,从而提高读操作的吞吐量或者降低时延。
MongoDB驱动允许客户端应用对于每个连接、每个collection或者每个操作进行读偏好设置。
读偏好模式同样对通过mongos连接分片簇的客户端有效。
注意:如果一个应用的读操作比例很大,则从secondary成员分布式读可以提高吞吐量。
读偏好模式:
primary
所有的读操作只访问当前副本集的primary,为默认模式。如果primary不可用,则读操作会产生一个error或抛出一个异常。
primaryPreferred [prɪ'fɜ:d]
在通常情况下,从副本集的primary上读数据,当primary不可用时,也就是在故障切换的过程中,从副本集的secondary成员上读数据。
secondary
读操作只从副本集的secondary成员上读数据。如果没有secondary可用,则产生一个error或者抛出一个异常。
secondaryPreferred
在通常情况下,读操作从secondary成员上读数据,但是当副本集中只有一个primary成员时,则从primary读数据。
nearest['nɪərɪst]
驱动从最近的集合成员中读数据时一个成员选择的过程。该模式不关注成员的类型,不管是primary还是secondary成员。
为了做离线处理 你可能希望创建很多索引,但是又不想将这些索引创建在主节点上 这种情况下 可以设置一个与主节点拥有不同索引的备份节点,如果希望这样使用备份节点的话 最好使用驱动程序创建一个直接连接目标备份节点的连接 而不是连接副本集
总结 应该根据应用程序的实际需求选择合适的选项 也可以多个选项组合使用
1,如果某些读请求必须从主节点读取数据,那就对这些请求使用Primary选项
2,如果另一些请求并不要求数据是最新的,那么可以对这些读请求使用Primary preferred选项
3,如果某些请求要求对延迟的要求打过一致性的要求 那么可以使用Nearest.