本文共 1493 字,大约阅读时间需要 4 分钟。
业务上并无对这个表的delete操作,通过mongostat可以查看。但是mongos对一个表进行count操作时,发现它的计数结果会慢慢变少,然后突然有一个大幅增长,随后又逐渐减少,现象如下
mongos> db.ebay_us_detail.count()
154462481 mongos> db.ebay_us_detail.count() 154462463 mongos> db.ebay_us_detail.find().count() 154686915 mongos> db.ebay_us_detail.find().count() 154686850 mongos> db.ebay_us_detail.find().count() 154686769 mongos> db.ebay_us_detail.find().count() 154873243 mongos> db.ebay_us_detail.find().count() 154873088我查了下oplog,发现某个分片上存在这么一个操作,标记为d,即delete操作
udb-dm5jbg:PRIMARY> db.oplog.rs.findOne({"ns":"ebay.ebay_us_detail","op":"d"})
{ "ts" : Timestamp(1514210377, 16), "t" : NumberLong(2), "h" : NumberLong("-6024794084103163788"), "v" : 2, "op" : "d", "ns" : "ebay.ebay_us_detail", "fromMigrate" : true, "o" : { "_id" : ObjectId("5a3a5f1d71c2475fee1f26b6") } }通过这条记录大概猜测后台正在move chunk,通过mongod日志确认后台确实正在针对该表进行move chunk,猜测这是一个bug
1 通常情况下,一个分片上的数据属于该分片上的chunk
2 然而在move chunk过程中,如果move chunk没有完成,数据虽然还在这个分片上,但是这个chunk已经不属于这个分片了
3 这时在这个分片上执行count时,只会统计在这个分片上并且属于这个分片的chunk的记录数,不会统计在这个分片上但不属于这个分片的chunk上的记录数,所以count操作会不准,出现上述的故障现象,慢慢减少,突然又增加
4 如果是非count操作,普通的query肯定无法容忍这种错误的,所以非count操作会额外去查看在这个分片上,需要的chunk确实属于该分片;如果该chunk不属于该分片,则操作会被阻塞,直到move chunk完成。所以move chunk时的性能会急剧下降,但是确保数据正确
5 count为啥不去额外统计不属于这个分片的chunk呢,这既是一个bug,也是一种折中的考虑。可以认为一般业务并不需要非常精准的count结果,但是count速度比较重要,不去额外统计的话,就可以使用覆盖索引,而检查某个记录是否属于一个有效的chunk这种操作是个比较费时的操作,无法使用索引
1 修改源码,count统计方法和普通query一样,即正确性第一,效率第二
2 设置负载均衡窗口期,在窗口期内业务不要指望准确的count操作
https://jira.mongodb.org/browse/SERVER-8405
转载地址:http://bcbgb.baihongyu.com/