现象:mysql
同事负责的项目转到我部门,整理服务过程当中发现了队列的积压问题。redis
为了搞清楚积压的严重程度, 对队列任务数每分钟进行一次采样,生成一个走势图, 队列积压状况一目了然,很是严重。 sql
分析:mongodb
听了同事对系统的介绍,猜想是mongo性能影响了处理效率,因而针对mongo进行分析shell
1. 使用mongotop /usr/local/mongodb/bin/mongotop --host 127.0.0.1:10000数据库
odds_easy.basic_odds表的操做一直排第一,写操做占大部分时间json
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做为配置服务中心以及热数据导入的流程控制中心
架构图
update_betting_offer队列的GermanWorker启动新增流程
在german注册一个任务名称,名字为第一步中的节点内容
"本机IP进程号_update_setting"任务处理流程:
定时任务流程:
初赔结构, key值: “event_id:betting_id:start” , value值为hash类型,hash_key:provider_id;hash_value:跟mongo中的结构一致,json格式;如{"i":{"t0":{"h":4.27,"d":3.24,"a":1.88},"t1":0.9305,"t2":{"h":0.2179,"d":0.2872,"a":0.4949},"t3":{"h":0.93,"d":0.93,"a":0.93}},"s":1,"t":"2017-04-03 13:39:28","b":0,'p':744 }
终赔结构,key值:"event_id:betting_id:end" value值同初赔
平均结构,key值:"event_id:betting_id:avg" value值同初赔
变化过程,key值:"event_id:betting_id:provider_id:boundary", value值为sorted set, member为赔率信息,跟mongo中的结构一致,json格式;如{"i":{"t0":{"h":4.27,"d":3.24,"a":1.88},"t1":0.9305,"t2":{"h":0.2179,"d":0.2872,"a":0.4949},"t3":{"h":0.93,"d":0.93,"a":0.93}},"s":1,"t":"2017-04-03 13:39:28","b":0,'p':744 }。 score为时间,如20170403133928
若是按照上面的结构进行存储, 进行了大概的预估。
对2789场比赛进行了欧赔统计,平均一场比赛2006个初赔,2006个终赔;583个boudary值,每一个boundary结构中存23个赔率变化;这样计算一场比赛须要大概 5.5m, 盘口数据大概为欧赔的一半。总8M
若是放入全部未开赛的比赛,大概1个半月的比赛,1w场比赛,所需内存80G,这个量太大了。
因此只放入热数据,2天内未开赛的比赛,保存3天,3天比赛450场左右。 须要 3.6G
----------------后续:第一阶段优化完后高峰期最高120左右