mongodb是如何保障数据真正写入的

对于mysql来说,只要数据写入主库,就代表持久化成功了,即使主库挂了,数据是不会丢失的,但主库是单点,无法保障高可用性,即使使用主从切换策略,mysql本身是不支持分布式的。

而对于mongodb这样的分布式软件来说,其本身就支持高可用和扩展性,通过分片可以支持数据的横向扩容,通过副本集的复制和切换原生支持高可用。

主副本集挂掉后,通过心跳检测会选举一个从副本集成为主副本集,而这些对应用是透明的。

默认情况下,应用更新数据的时候,主副本集响应成功就代表数据更新成功了,此时oplog拷贝给其他副本集,如果此时没有同步完成,主副本集挂了,此时会出现什么情况?

某个副本集成为主副本集,然后接收应用的查询和更新,保证服务不受影响,当原有的主副本集恢复后,原来的更新就回滚了,等于数据丢失了,这对于某些场景的应用,肯定是不可接受到。

此时就要用到Write Concern概念,它是在性能和数据持久性之间的一个平衡,而mongodb把这种平衡的抉择交给了应用程序。

默认write concern of w等于1,表示主副本集更新成功就发送ack给应用程序,为了数据持久性,可以选择w为majority,代表大部分副本集同步成功了,才发送ack给应用程序。

由于大部分副本集写入成功了,那么即使主副本集挂了了,通过选举能够找到一个较新数据的副本集,让其成为primary副本集,从而避免写入回滚。

那使用w为majority的缺点是什么呢,就是性能,应用程序必须等待,而且可能会阻塞,为了避免阻塞,可以设置一个超时时间。

如果出现超时,只是代表在指定时间内从副本集没有确认ack写入,不代表主副本集不能写入,但此时应用可能需要其他策略确保更新不会归滚,比如read preference。

Applications should take into account the potential availability of written data regardless of the state of write concern acknowledgment.

使用mongo shell:

db.products.insert(
   { item: "envelopes", qty : 100, type: "Clasp" },
   { writeConcern: { w: "majority" , wtimeout: 5000 } }
)

使用php mongo:

$client = new MongoDB\Client("mongodb://localhost:27017",["w"=>"MAJORITY","wTimeoutMS"=>200
0]);
var_dump($client->getWriteConcern());
我来评几句
登录后评论

已发表评论数()

相关站点

热门文章