首页
社区
课程
招聘
[原创]数据存储系统的优化之路
发表于: 2020-3-17 22:49 4780

[原创]数据存储系统的优化之路

2020-3-17 22:49
4780
大家在玩鹅厂系游戏的时候应该看到过xxxRpcs.dll  TCJ.dll  ProbePolicy.dll 这样的dll,会上报一些游戏内和游戏外的数据。游戏内的数据比如游戏的某个函数被call了多少次,call的参数有没有被人为修改,调用来源是否合法...甚至键盘某个键按下了多少次(对比正常玩家和开挂玩家之间的数据差异来抓外挂)。游戏外的数据比如你开了哪些进程,开了哪些窗口,如果是不认识的进程是不是要hash一下把hash也上报服务器。这些数据大多都是“ 时序数据 ”。

时序数据有什么特点?百度上面的解释太多了,我用我自己的话描述一下:

1、写入(insert)量非常大、更删查(update delete select)很少甚至没有

2、数据之间没有关联性,用搞web的话说就是没有join

3、数据一般不会永久保留,XX天之后就会删除(也就是说有按日期批量删除的需求)

据不可靠消息来源,鹅厂TP的外挂数据存储是mysql(你信吗?我反正不信)

笔者四年前开发外挂数据存储时第一次用的就是mysql,写入性能捉鸡,上报用户数量一多,mysql的cpu使用率就暴涨,没一会儿mysql自己卡死,上层服务就全挂掉了

4核8G内存mysql顶多只能写入几百一千条/s,这还是开了TRANSACTION的情况下的,要是一条一条裸奔INSERT,那效率惨不忍睹....

而且当每天增长几GB数据、不得不面临加硬盘/清理旧数据的选择的时候

加硬盘?more money please

清理旧数据?delete from XXX where time < YYY 然后锁表慢慢跑去吧...没个七八个小时别想跑完

后来调研了一波当时市面上存在的写入性能比较好的数据库,相中了mongodb,但是也是撑死只能做到 16核32G 3000条/s,最高峰维持在40%CPU使用率(如果降低到8核的话业务最高峰99%使用率瞬间爆炸)。

随之而来的是每个月10K+ RMB的数据库费用...

而且更坑爹的是,mongodb在当前业务中完美继承了mysql的那些缺点:

删数据=锁表

锁表就算了,我整个表直接drop

偶尔的查字符串$regex:{xx:'yyy'} = 漫长的等待

我打完字符串查询语句,去泡了杯茶

回来一看,emm还在查询...下楼去买他一波饮料。

回来一看,emm还在查询...当我正要点Cancel把查询operation kill掉的时候。

查询结果出来了。本次共查询到了5个document(s),耗时10mins 35 secs

这mongodb还让不让人干活儿了。

咱不受这气!换!

一个月后我把之前的纯mongo存储换成了elasticsearch+mongo双存储。

一开始是上层服务直接往es bulk数据,一次几十~一百多条,一到高峰期就疯狂es reject,优化了index的refresh interval也没啥用。

考虑到es是通过HTTP client写入的,一秒几十个后端服务同时发起几百个bulk和get请求这http怕是吃不消。

后来我把写入逻辑改成了上层服务把所有数据写到logstash,logstash再往es写数据,一次写1500条,大幅度减少了同时发起的HTTP请求。

elasticsearch只存纯时序数据,按日期拆分index。

mongo只存可能需要中途更新或者频繁修改的数据,修改完成之后同步一份完整数据到es。

用3节点es成功做到了最高峰3000 index /s,  0 reject

考虑到用logstash首次迁移数据时最高是8000条/s,所以以目前的配置哪怕最高峰承载的人数翻一倍问题也不是很大。

总结:es大量写入数据务必通过logstash,避免大量零散get/mget,否则非常容易因为同时发起的请求过多导致reject 。

目前mongo和es最高峰的cpu使用率都在40%以下,而且数据库费用也降到了原来的五分之一。

按日期拆分index之后每天还能用es自带的生命周期管理功能自动清理旧的数据,最爽的是搜索字符串1秒内出结果。

芜湖~起飞

如果不考虑数据时效性(数据延迟几个小时)为了节约成本还能继续优化,把数据放到kafka之类的磁盘队列里面,然后在业务低峰期(比如深夜凌晨)写入,能够平衡高峰和低峰期的服务器负载。

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 3
支持
分享
最新回复 (2)
雪    币: 6910
活跃值: (3410)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
asd
2
一个人整一套系统的大佬
2020-3-26 15:07
0
雪    币: 137
活跃值: (1275)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
我的方案是redis+MongoDB,用户内存信息之类的数据只保留最新的在没有可疑的内存情况下,用户断开连接或者redis timeout之前都写到redis里面,断开或者time out后再写MongoDB 就是挺耗内存,堆内存就行,其他的没啥问题
2021-2-4 19:45
0
游客
登录 | 注册 方可回帖
返回
//