数据库连接
使用DDS时,可能会遇到因为 Mongod/Mongos 连接数用满了,导致客户端无法连接的问题。在Mongod/Mongos的服务端,收到一个新的连接由一个单独的线程来处理,每个线程配置了1MB的栈空间,当网络连接数太多时,过多的线程会导致上下文切换开销变大,同时内存开销也会上涨。
- 客户端连接数据库的时候,要计算业务一共有多少个客户端,每个客户端配置的连接池大小是多少,总的连接数不要超过当前实例能承受的最大连接数的80%。
- 对于副本集,客户端需要同时配置主备节点的IP地址, 对于集群,至少配置两个mongos的IP地址。
- DDS默认提供rwuser用户,使用rwuser用户登录时认证库必须是admin。
可靠性
write concern设置规则:对于关键业务,write concern设置为{w:n},n>0,数字越大,一致性实现更好,但性能较差。
- w:1表示实际写入主节点完成返回。
- w:1,journal:true表示写主节点和日志后返回。
- w:majority表示大多数备节点写入后返回。
对于可靠性有较高要求的,建议采用3az部署的集群。
性能相关
规范
- 业务程序禁止执行全表扫描的查询。
- 执行查询时,只选择需要返回的字段,不需要的字段不要返回。从而减少网络和进程处理的负载,修改数据时,只修改变化需要修改的字段,不要整个对象直接存储全部修改。
- 避免使用not。DDS并不会对缺失的数据进行索引,因此not的查询条件将会要求在一个结果集中扫描所有记录。如果$not是唯一的查询条件,会对集合执行全表扫描。
- 用and时把匹配最少结果的条件放在最前面,用or时把匹配最多结果的条件放在最前面。
- 单个实例中,数据库的总的个数不要超过200个,总的集合个数不要超过500个。
- 业务上线前,一定要对数据库进行性能压测,评估业务峰值场景下,对数据库的负载情况
- 禁止同时执行大量并发事务,且长时间不提交。
- 业务正式上线前, 所有的查询类别,都应该先执行查询计划检查查询性能
建议:
- 每个连接在后台都是由一个单独线程处理,每个线程会分配1MB的栈内存。所以连接数不宜过多,否则会占用过多的内存。
- 使用连接池,避免频繁的建立连接和断开连接,否则会导致CPU过高。
- 减少磁盘读写:避免使用不必要的upsert命令,避免查询不必要的数据。
- 优化数据分布:对数据进行分片,同时分散热点数据,均衡地使用实例资源。
- 减少锁冲突:避免对同一个Key,过频繁地操作。
- 减少锁等待:避免前台创建索引。
注意:
开发过程中对集合的每一个操作都要通过执行explain()检查其执行计划,如:
db.T_DeviceData.find({"deviceId":"ae4b5769-896f"}).explain();
db.T_DeviceData.find({"deviceId":"77557c2-31b4"}).explain("executionStats");
对于查询而言,因为覆盖查询不需要读取文档,而是直接从索引中返回结果,这样的查询性能好,所以尽可能使用索引覆盖查询。如果explain()的输出显示indexOnly字段为真,则说明这个查询就被一个索引覆盖。
执行计划解析:
看执行时间:executionStats.executionStages.executionTimeMillisEstimate和executionStats.executionStages.inputStage. executionTimeMillisEstimate时间越短越好。
− executionStats.executionTimeMillis表示执行计划选择和执行的所有时间。
− executionStats.executionStages.executionTimeMillisEstimate表示最优执行计划的执行完成时间。
− executionStats.executionStages.inputStage. executionTimeMillisEstimate表示最优执行计划下的子阶段执行完成时间。
看扫描条数:三个条目数相同为最佳。
− executionStats. nReturned表示匹配查询条件的文档数。
− executionStats .totalKeysExamined表示索引扫描条目数。
− executionStats .totalDocsExamined表示文档扫描条目数。
看Stage状态,性能较好的Stage状态组合如下。
− Fetch+IDHACK
− Fetch+ixscan
− Limit+(Fetch+ixscan)
− PROJECTION+ixscan
表 状态说明
状态名称 | 描述 |
---|---|
COLLSCAN | 全表扫描 |
SORT | 内存中进行排序 |
IDHACK | 根据_id进行查询 |
TEXT | 全文索引 |
COUNTSCAN | 未用索引计数 |
FETCH | 索引扫描 |
LIMIT | 使用Limit限制返回数 |
SUBPLA | 未用索引的$or查询阶段 |
PROJECTION | 限定返回字段时stage的返回 |
COUNT_SCAN | 使用索引计数 |
Cursor使用规则
如果cursor不使用了要立即关闭。由于cursor在10分钟内不活动,就会关闭,立即手动关闭会节省资源。
4.2版本分布式事务使用规则
- Spring Data MongoDB不支持事务报错后重试机制,如果客户端使用Spring Data Mongo作为连接MongoDB的客户端,需要依照Spring Data Mongo的参考文件,使用Spring Retry进行事务的重试操作。
- 分布式事务操作数据的大小不能超过16MB。