文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

MongoDB读数据策略

2024-11-30 17:33

关注

图片来源:db-engines

在MongoDB读取数据主要是受read concern(读策略)、read preference (读偏好设置 )两个参数控制,其中readconcern决定在读取副本集和分片集数据时的一致性和隔离性,而readpreference 决定客户端驱动读取哪个数据节点的数据。它们的配合使用,可以提高MongoDB 集群的性能,以及在数据一致性和读性能上做平衡。

readconcern 一致性读策略

Readconcern 主要解决脏读问题,从3.2版本后开始支持。比如PSA集群,用户从 MongoDB 的 primary 上读取数据后,这条数据并没有同步从数节点,然后 primary 就故障了。此时不同的Readconcern值,MongoDB 返回数据的处理方式是不同的。

Readconcern有几个不同的参数,分别是local、available、majority、linearizable、snapshot ,数据库在这些参数下的一致性是由弱到强递增的。

◀几种模式介绍▶

表示读取的数据从实例中返回数据,但不保证数据是否被持久化(即可能被回滚)。该参数默认值为local。

表示读取的数据从实例中返回数据,但不保证数据是否被持久化(即可以回滚)。乍一看available和local没有啥区别,对于副本集架构两者是相同的,主要区别场景是分片群集。在分片集群下,数据迁移会出现孤儿文档(orphaned document),available模式可以从延迟最低的节点获取数据,而local则直接返回数据。该参数是3.6版的新功能。

表示读取返回多数副本集成员已确认的数据,这个数据是持久化的不会被回滚。需要注意,在Majority下只能保证读到的数据“不会发生回滚”,但并不能保证读到的数据一定是最新的,官方也明确做了说明。

Regardless of the read concern level, the most recent data on a node may not reflect the most recent version of the data in the system。

线性读取数据。根据官方资料翻译成中文:该查询返回的数据,反映了在读取操作开始之前完成的所有成功的多数确认写入。查询可能会等待并发执行的写操作传播到大多数副本集成员,然后返回结果。也就是在这种模式下,读可能需要等待其他写操作完成。

从最新的快照中读取数据。如果事务不是因果一致的会话的一部分,并且数据的写入参数writeconcern 值也是majority下,那将从多数提交数据的快照中读取数据。

一般在生产推荐配置成Majority,这种模式是在数据安全和性能上相对平衡的选择,但是使用Majority也有要求和问题。首先它只支持WiredTiger引擎,其次需要写入参数writeconcern 也是majority 才会生效,最后在Majority下也不能完全保证解决了脏读问题。

◀Majority 实现▶

MongoDB 在readconcern majority 下,数据库会起一个单独的snapshot 线程,周期性的对当前的数据集进行 snapshot,并记录 snapshot 最新 oplog的时间戳,得到一个映射表。

最新 oplog 时间戳

snapshot

状态

t0

snapshot0

committed

t1

snapshot1

uncommitted

t2

snapshot2

uncommitted

t3

snapshot3

uncommitted

当 oplog 同步到大多数节点时,对应节点的 snapshot 才会标记为 commmited,用户读取时,从最新的 commited 状态的 snapshot 读取数据,就能保证读到的数据一定已经同步到的大多数节点。那如何判断oplog 已经同步到大多数节点?

对于primary来说,当secondary 节点的oplog发生变化时,会通过命令将 oplog 进度立即通知给 primary,同时节点间的心跳消息里也会包含最新 oplog 的信息。这样primary 节点能很快知道数据是否已经同步到大多数节点的,并更新 snapshot 的状态。比如当t2已经写入到大多数据节点时,snapshot1、snapshot2都可以更新为 commited 状态。

对于secondary 节点来说,在拉取 oplog 时,primary 节点会将“最新的数据已同步到大多数节点的”的信息返回给 secondary 节点,然后secondary 节点通过这个oplog时间戳来更新自身的 snapshot 状态。

readpreference 读偏好设置

MongoDB 读控制策略除了readconcern策略外,还有readpreference 。它主要控制数据库客户端驱动从哪个节点读取数据。这个特性可以方便地实现读写分离、就近读取等策略。

readpreference 是由三部分组成,分别是mode、maxStalenessSeconds 、tag set,其中mode支持五种类型,分别是:primary、primaryPreferred、Secondary、secondaryPreferred、nearest,我们先看几种模式的具体含义。

◀几种模式介绍▶

默认模式。读操作只在主节点,如果主节点不可用,报错或者抛出异常。这种策略适用于应用程序需要严格的一致性,但可用性不是首要考虑因素的情况。

大多情况下读操作在主节点,如果主节点不可用,如故障转移,读操作在从节点。

仅从secondary节点中读取,如果secondary节点不可用,读将会报错。

大多情况下读操作在从节点,特殊情况(如没有从节点)读操作在主节点。

根据指定的延迟阈值,随机地从符合条件的数据节点中读取操作,不管该节点是主还是从节点。

◀maxStalenessSeconds▶

MongoDB 3.4 以后版本新增maxStalenessSeconds参数。集群的从节点可能因为网络阻塞、磁盘吞吐低、长时间执行等原因,使从节点落后于主节点。当从节点延迟时间超过了该参数定义的值,客户端不会从该节点读取数据。maxStalenessSeconds 不能与primary 模式兼容,只能在其他四种模式下使用。

当选择了使用该参数控制读取数据,客户端会通过比较从节点和主节点的最后一次写时间来估计从节点的过期程度。客户端会把连接指向小于等于maxStalenessSeconds的从节点。另外,需要注意maxStalenessSeconds最小值是90秒,如果小于该值将报错。

You must specify a maxStalenessSeconds value of 90 seconds or longer: specifying a smaller maxStalenessSeconds value will raise an error.

◀标签集▶

如果一个复制集中的成员有tag,就可以通过下面的办法读取到带有具体标签的成员上。例如,如果某个节点有这样的成员标签:

{ "region": "South", "datacenter": "A" }
那么以下tag set可以将读操作指到上述成员(或具有相同标记的其他成员):
[ { "region": "South", "datacenter": "A" }, { } ]     // Find members with both tag values. If none are found, read from any eligible member.
[ { "region": "South" }, { "datacenter": "A" }, { } ] // Find members with the specified region tag. Only if not found, then find members with the specified datacenter tag. If none are found, read from any eligible member.
[ { "datacenter": "A" }, { "region": "South" }, { } ] // Find members with the specified datacenter tag. Only if not found, then find members with the specified region tag. If none are found, read from any eligible member.
[ { "region": "South" }, { } ] // Find members with the specified region tag value. If none are found, read from any eligible member.
[ { "datacenter": "A" }, { } ] // Find members with the specified datacenter tag value. If none are found, read from any eligible member.
[ { } ] // Find any eligible member.

◀访问案例▶

总结上面的内容,可以通过下面三种方式去定义不同的readpreference策略。

复制集访问方式:
mongodb://db0.test.com,db1.test.com,db2.test.com/?replicaSet=myRepl&readPreference=secondaryPreferred&maxStalenessSecnotallow=150
分片集群方式:
mongodb://mongos1.test.com,mongos2.test.com/?readPreference=secondaryPreferred&maxStalenessSecnotallow=150
带tag的定式:
mongodb://mongos1.test.com/?readPreference=secondaryPreferred&readPreferenceTags=dc:ny,rack:r1&readPreferenceTags=dc:ny&readPreferenceTags=xxx

总结

通过上文介绍,我们知道MongoDB读数据策略,有readconcern和readpreference两个重要的概念。其中readconcern是读数据时的数据一致性级别,它决定了决定读取数据时读到什么样的数据。通常结合可用性和性能,会将readconcern设置为majority。而readpreference决定读哪个节点的数据,主要用于实现读写分离上。另外,MongoDB还提供了其他的配置选项,如写数据策略(writeconcern)这将在后面的文章中介绍。

作者介绍

司马辽太杰是 NineData 工程师。NineData 向企业和个人提供高效、安全的数据库SQL开发、数据库备份、数据复制/迁移/集成、数据对比等能力的产品,它是开箱即用的SaaS服务,可以快速提升企业SQL开发效率,保障企业数据安全。近期,NineData 即将会支持MongoDB、Redis等NoSQL数据库。NineData 官网地址:​​https://ninedata.cloud/​​。

本文转载自微信公众号「云数据库技术」,可以通过以下二维码关注。转载本文请联系云数据库技术公众号。

来源:云数据库技术内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯