软件设计 2017-04-26
现象:
同事负责的项目转到我的头上,整理服务过程中发现了队列的积压问题。
为了搞清楚积压的严重程度, 对队列任务数每分钟进行一次采样,生成一个走势图, 队列积压情况一目了然,非常严重。
分析:
听了同事对系统的介绍,猜测是mongo性能影响了处理效率,于是针对mongo进行分析
1. 使用mongotop /usr/local/mongodb/bin/mongotop --host 127.0.0.1:10000
odds_easy.basic_odds表的操作一直排第一,写操作占大部分时间
2. 看mongo shard日志
大量超过1s的操作,集中在odds_easy.basic_odds写操作, 看日志lock数量很多
查询某一个文档的更新,在同一秒中居然有15个更新操作,这样的操作产生什么样的结果: 大量的写锁,并且影响读;而且还是最影响性能的数组的$push, $set操作
看看文档的结构,数组的数量之大,而且里面还是对象嵌套; 对这样一个文档不停的更新, 性能可想而知
看看 db.serverStats()的lock情况
看看odds_easy的db.basic_odds.stats()情况,大量的更新冲突
3. 看看sharding情况
使用脚本,查看sharding情况,重定向到文件中查看。 sql='db.printShardingStatus({verbose:true})' echo $sql|/usr/local/mongodb/bin/mongo --host 192.168.1.48:30000 admin --shell
basic_odds的sharding信息:
shard key: { "event_id" : 1, "betting_type_id" : 1 } event_id为mysql自增字段,betting_type_id为玩法id(意味着几个固定的值,区别度不大)
shard 分布情况, 从图里面可以看到mongo主要根据event_id这个自增字段的范围进行数据拆分, 意味着相邻比赛的数据大概率会被分配到同一个shard分区上(这就是为什么01机器上的日志大小远大于其他机器的原因吧,目前的数据都集中在shard1上)
下图为数据库读写情况, 更新操作是查询操作的4倍。 对一个写多读少的数据库, 本该将写操作分布到不同的分区上,结果由于sharding key的错误选择造成了写热点,将写集中到了同一个分区,进一步加剧了写的阻塞
【可以看到前期合理的架构设计是多么的重要】
分两个阶段:
目的
系统中加入redis做热数据缓存, zookeeper/etcd作为配置服务中心以及热数据导入的流程控制中心