高并发( 6M/s)日志数据如何准实时入库( MySQL)

2016-03-03 13:55:42 +08:00
 iyaozhen

目前已经使用 filebeat+logstash 将线上的实时请求日志推送到了 Redis ( list 数据结构做队列) 中。但现在的处理瓶颈卡在了从 Redis 里面取数据做聚合然后入库这步了。

因为数据聚合处理使用的是 Redis 的 hash 数据结构做计数器,需要和 Redis 有几次交互,单个脚本的处理速度为 0.03M/s (已经优化过了),开 200+ 个进程数据聚合这块应该是抗的住的。

一开始使用的方案是每个脚本缓存数据然后达到一定数量(比如 10w 行)后批量解析然后 insert 入库,但因为用的是myisam存储结构(这里有两个原因: 1.机器磁盘不大节省空间 2.数据需要做统计 count(*)等操作用的比较多),写入数据时会锁表,后来又分库( 4 个库)分表( 100 个表)。这个解决方案抗了一段时间后数据量增长又不行了( redis 队列里面的数据处理没有增加快)。

后来想想批量解析和入库这里比较耗时间会阻塞脚本继续读取 Redis 中的数据。就想把解析入库的操作异步出来,这时想了一个办法是把 10w 行日志写文件,然后把文件的路径放到另一个队列里面去,起一些脚本解析文件入库。但我还是想得太简单了,数据量太大了,写的文件太多直接把测试虚拟机的 inode 用完了,机器直接蒙逼了。当然可以 50w 、 100w 行写一次文件,但这感觉不是根本的解决之道,还会带来其它问题(比如单个脚内存消耗过大)。

我感觉我这些解决方法还是太落后了,不知道大神们有没有什么解决方案。

PS :脚本是用的 PHP , Python 、 Go 都可以,不过我感觉这个问题应该不是语言的问题。
为了防止我跑偏,说一下核心需求:准实时根据请求参数等聚合统计数据(用于了解线上实时情况做监控),较低延迟( 30min 内)将这些数据入库(每个日志都带有 logid ,用于定位问题)。

18024 次点击
所在节点    程序员
60 条回复
fds
2016-03-03 14:14:17 +08:00
有必要写入数据库么? logstash 做些统计,把结果数据发送到 influxdb 什么的记录下来,显示在监控里就好了吧?非得存原始数据入库?
jimrok
2016-03-03 14:22:04 +08:00
让数据库直接 load 数据会快很多,没有事务的保护。
iyaozhen
2016-03-03 14:24:31 +08:00
@fds 额,确实需要原始数据做查询,用于定位问题。还要至少存一周
swolf119
2016-03-03 14:25:11 +08:00
同感觉没必要入库,从上文来看,感觉入库的需求就是为了数据统计
那么数据统计是直接读的 mysql 分析的吗
iyaozhen
2016-03-03 14:28:10 +08:00
@jimrok 这个我也想过。但是还是数据量太大暂存的文件太多(应为分库分表了, load 的时候需要按库和表把文件生成好),会把磁盘的 inode 用完。
kier
2016-03-03 14:29:16 +08:00
对 elk 不了解,我们是吧数据存入 mongodb 的,然后脚本定时统计结果,将结果数据入 mysql, 然后定期将 mongo 中的老的日志数据导出备份;
iyaozhen
2016-03-03 14:29:16 +08:00
@swolf119 不只是数据统计,主要还是用于定位问题。
lxf1992521
2016-03-03 14:30:09 +08:00
根据我的经验,可以使用 graylog+elasticsearch 试试;
性能数据可以直接通过 graylog 的 RestAPI 获取,对应日志可以直接从 ES 文档数据库中获取;
yahoo21cn
2016-03-03 14:30:30 +08:00
数据库改成事务,弄一个 redis 队列存插入数据,单独一个进程每秒读取该进程一次写入数据库。
iyaozhen
2016-03-03 14:30:33 +08:00
@kier 谢谢,我看看 mongodb ,对这个不是太了解。估计可行
iyaozhen
2016-03-03 14:32:40 +08:00
@lxf1992521 非常感谢,已经在看 elasticsearch 了,其实我也是用的 ELK 这一套,只是因为一些历史原因,只用了一部分。 graylog 这还没接触过,我看看。
iyaozhen
2016-03-03 14:35:55 +08:00
@yahoo21cn 用 myisam 存储的原因我已经说了, innodb 也试过,主要还是数据占用磁盘空间大,统计慢。「单独一个进程每秒读取该进程一次写入数据库。」我现在就是这样,已经 300+的进程在跑, redis 还是爆了。我不光是要入库,还要做一些实时聚合。
lynnworld
2016-03-03 14:38:38 +08:00
你的 insert 是批量 insert 的么,现在是解析耗时还是存入耗时多?
kier
2016-03-03 14:41:00 +08:00
对了,你们的日志是 nginx 或者 webapp 的请求处理日志,还是业务的埋点数据?
tabris17
2016-03-03 14:41:12 +08:00
看来你需要的是 spark
fds
2016-03-03 14:42:14 +08:00
定位问题的话直接用 lnav 扫 log 不就行了?真的有必要数据库查询吗?
elasticsearch 比较吃配置哦。
有钱的话,直接上 http://www.splunk.com/

其实你想用到数据库的什么功能呢?一些查询除非预先 index ,否则和直接遍历文本相比没有特别的优势呀。
iyaozhen
2016-03-03 14:43:14 +08:00
@lynnworld 是批量的。两者都比较多。抱歉,这里没做具体的统计。
因为是批量解析 10w 条日志,还要分库分表。其实单次 insert 还比较快,但并发高,数据库会锁表,有些请求就等待了。
iyaozhen
2016-03-03 14:44:15 +08:00
@kier 业务埋点数据,一个用户请求会过服务器很多模块,每个模块都会打日志,所以量比较大。
iyaozhen
2016-03-03 14:45:06 +08:00
@tabris17 这东西听说过,我研究下。
iyaozhen
2016-03-03 14:48:50 +08:00
@fds 线上几十上百台机器,还在不同机房,每个机器还有 10+的模块,还是比较蛋疼,而且还要其它一些需求,比如定位查询结果可视化等。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.fyfyfm.apispeedy.workers.dev/t/260806

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX