ITPub博客

首页 > 数据库 > NoSQL > MongoDB从库延迟读取数据问题的解决思路

MongoDB从库延迟读取数据问题的解决思路

原创 NoSQL 作者:chenfeng 时间:2016-01-14 13:17:15 0 删除 编辑
最近,在网上看到一个朋友的MongoDB遇到性能问题,问题是这样的:
主库更新了数据,其中一个从库时读取,配置了后发现有延迟,比如更新50条,从库只能读取50%的数据,如何解决?

解决思路:

1) 监测一下网络看是否有瓶颈
2) 确认主从配置是否一致 (CPU、内存和IO)
3) 使用WriteConcern把数据同步写到从机


那么WriteConcern是怎么把数据同步写到从机的,下面介绍一下MongoDB的WriteConcern参数

首先列一下WriteConcern的几种抛出异常的级别参数:
WriteConcern.NONE:没有异常抛出
WriteConcern.NORMAL:仅抛出网络错误异常,没有服务器错误异常
WriteConcern.SAFE:抛出网络错误异常、服务器错误异常;并等待服务器完成写操作。
WriteConcern.MAJORITY: 抛出网络错误异常、服务器错误异常;并等待一个主服务器完成写操作。
WriteConcern.FSYNC_SAFE: 抛出网络错误异常、服务器错误异常;写操作等待服务器将数据刷新到磁盘。
WriteConcern.JOURNAL_SAFE:抛出网络错误异常、服务器错误异常;写操作等待服务器提交到磁盘的日志文件。
WriteConcern.REPLICAS_SAFE:抛出网络错误异常、服务器错误异常;等待至少2台服务器完成写操作。

当我们执行如下操作时(将"name"为"lily"的"age"设置为20):

db.update({"name":"lily"},{"$set":{"age":20}})
默认情况下,该操作会使用WriteConcern.NORMAL(仅在网络错误时抛出异常),等同于:

db.update({"name":"lily"},{"$set":{"age":20}},WriteConcern.NORMAL)
使用NORMAL模式参数,可以使得写操作效率非常高。但是如果此时服务器出错,也不会返回错误给客户端,而客户端会误认为操作成功。

因此在很多重要写操作中需要使用WriteConcern.SAFE模式,保证可以感知到这个错误,保证客户端和服务器对一次操作的正确性认知保持一致。

(根据笔者测试,如果服务器发生掉电情况,客户端依然得不到当时操作的错误返回,需要特别注意)

另外在很多时候,我们需要确切知道这次写操作是否成功(或者本次更新操作影响了多少个对象),这时候就需要:

WriteResult ret = db.update({"name":"lily"},{"$set":{"age":20}});
if(ret.getN()>0) //操作影响的对象个数
    return true;
else
    return false;
或者:
WriteResult ret = db.update({"name":"lily"},{"$set":{"age":20}});
if(ret.getLastError() == null)
    return true;
else
    return false;

此时,getLastError()会查询上次操作结果是否出现错误。

更进一步
然后由于mongodb中使用连接池的原因,getLastError()需要再次从连接池中获取连接,这样效率会慢一些。可以这样做:

db.requestStart();
WriteResult ret = db.update({"name":"lily"},{"$set":{"age":20}});
if(ret.getLastError() == null)
    return true;
else
    return false;
db.requestDone();
就可以保证update操作和getLastError()使用同一个连接,并且减少了一次存/取连接的过程。



来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/15498/viewspace-1976412/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
交流MySQL,PolarDB/PolarDB-X,PostgreSQL,MongoDB和Redis技术。

注册时间:2015-12-07

  • 博文量
    784
  • 访问量
    2691178