V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iyaozhen
V2EX  ›  程序员

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

  •  
  •   iyaozhen ·
    iyaozhen · 2016-03-03 13:55:42 +08:00 · 18145 次点击
    这是一个创建于 3192 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前已经使用 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 ,用于定位问题)。

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

    其实你想用到数据库的什么功能呢?一些查询除非预先 index ,否则和直接遍历文本相比没有特别的优势呀。
    iyaozhen
        17
    iyaozhen  
    OP
       2016-03-03 14:43:14 +08:00
    @lynnworld 是批量的。两者都比较多。抱歉,这里没做具体的统计。
    因为是批量解析 10w 条日志,还要分库分表。其实单次 insert 还比较快,但并发高,数据库会锁表,有些请求就等待了。
    iyaozhen
        18
    iyaozhen  
    OP
       2016-03-03 14:44:15 +08:00
    @kier 业务埋点数据,一个用户请求会过服务器很多模块,每个模块都会打日志,所以量比较大。
    iyaozhen
        19
    iyaozhen  
    OP
       2016-03-03 14:45:06 +08:00
    @tabris17 这东西听说过,我研究下。
    iyaozhen
        20
    iyaozhen  
    OP
       2016-03-03 14:48:50 +08:00
    @fds 线上几十上百台机器,还在不同机房,每个机器还有 10+的模块,还是比较蛋疼,而且还要其它一些需求,比如定位查询结果可视化等。
    zhicheng
        21
    zhicheng  
       2016-03-03 14:54:30 +08:00
    1. 优化写入,优化一下 MySQL 的参数,甚至极端一些关掉日志等。
    2. 优化计算,聚合计算和数据存储分开,保存聚合计算的结果,在这个结果之后做增量计算。
    3. 精度换速度,自己实现聚合函数,提供几个关键词, bloomfilter, hyperhyperlog 。
    lynnworld
        22
    lynnworld  
       2016-03-03 15:17:59 +08:00
    话说 6m 是 6 百万条日志嘛?那一天不都有上千亿日志了。平均日志大小是多少啊?
    kier
        23
    kier  
       2016-03-03 15:36:14 +08:00
    6 兆吧,一条日志就算有 200 字节,那么大概 3W 条每秒?
    solupro
        24
    solupro  
       2016-03-03 15:39:29 +08:00
    /dev/shm , load data infile 不知道能扛多少
    iyaozhen
        25
    iyaozhen  
    OP
       2016-03-03 15:50:08 +08:00
    @lynnworld 流量, 6MB/s (高峰)。一天差不多快 10 亿条日志了。
    zeeler
        26
    zeeler  
       2016-03-03 16:00:43 +08:00
    日志建议用 mongodb 之类的 nosql 数据库
    realpg
        27
    realpg  
       2016-03-03 16:09:44 +08:00
    @iyaozhen
    有没有试过 insert delayed into
    wweir
        28
    wweir  
       2016-03-03 16:13:56 +08:00 via Android
    MySQL 有一个存储引擎是专门干日志这些个破事的。叫 Archive ,可以尝试一下。
    话说存这些个死的数据,直接压缩一下放那多好。非要存数据库,还非要要关系型数据库。
    vus520
        29
    vus520  
       2016-03-03 16:19:56 +08:00
    elk ,生产中 10 台服务器,两个 logstash 可以做到 4k 左右的写入速度
    ango
        30
    ango  
       2016-03-03 16:26:53 +08:00
    多级(如: IP/date/module/……)划分目录,直接同步到一台日志文件服务器(硬盘大、内存大),不管你是要定位或者清洗什么数据,直接 python 或者 shell 脚本定制,这样的处理挺快的,后期将定制基本集中起来做个管理化系统。

    目前对于上百台服务器程序输出的日志,这样使用还没发现什么不方便或者大问题。
    iyaozhen
        31
    iyaozhen  
    OP
       2016-03-03 16:27:21 +08:00
    @zeeler 谢谢,正在调研。 mongodb 没怎么实际用过,主要是怕从一个坑跳到另一个坑中。
    iyaozhen
        32
    iyaozhen  
    OP
       2016-03-03 16:27:51 +08:00
    @realpg 试过,然后数据库扛不住了。 233333
    xgdyhaiyang
        33
    xgdyhaiyang  
       2016-03-03 16:27:59 +08:00
    之前用 C 写过一个专门往 MYSQL 写日志的系统,支持自定义配置字段,支持自动分表和按自然时间切换表,支持缓存批量入库,支持队列抵御高峰。,支持删除过期数据。

    https://github.com/haipome/logdb

    之前测试过 MYSQL 用 myisam 存储引擎,每秒中写几万条没有问题的,一天 10 亿应该也扛得住。
    yuankui
        34
    yuankui  
       2016-03-03 16:28:56 +08:00
    我们的日志规模,现在是每秒 4 万条

    用的 ELK

    消息队列用的是 kafka,redis 不靠谱!

    后来 logstash 出现了严重的性能问题,cpu 占用超过应用本身,我们又用 Java 语言重写了 logstash(没用实现 DSL),性能提高了 10 倍.

    现在系统没啥压力.

    不够话说性能指标相关的,完全可以 metrics+influxdata+grafana 来做,可以大大减少数据量的存储
    iyaozhen
        35
    iyaozhen  
    OP
       2016-03-03 16:31:42 +08:00
    @ango 嗯嗯,日志转存这个其它地方也在做。主要是现在还有对数据流监控的需求。
    realpg
        36
    realpg  
       2016-03-03 16:31:56 +08:00
    @iyaozhen
    你数据库服务器存储的 IO 性能如何?
    我这边的这种密集清一色带缓存混合阵列,写数据库速度飞快。
    因为日志这种, SSD 实在玩不起……
    iyaozhen
        37
    iyaozhen  
    OP
       2016-03-03 16:41:11 +08:00
    @yuankui 嗯,谢谢。应该实现多看看业界是怎么搞的。不能自己瞎搞,关键是自己还很菜。
    iyaozhen
        38
    iyaozhen  
    OP
       2016-03-03 16:42:23 +08:00
    @realpg 线上机器的话应该是 16/32 核, 128 内存。但硬盘不是 SSD 的。。。
    realpg
        39
    realpg  
       2016-03-03 16:43:41 +08:00
    @iyaozhen
    我说的就是你的磁盘,读写性能如何。
    你说的 MYSQL 死了应该不是 CPU 爆了,就是卡 IO 了,明显 IO 瓶颈了啊。
    lynnworld
        40
    lynnworld  
       2016-03-03 16:55:27 +08:00
    "
    因为数据聚合处理使用的是 Redis 的 hash 数据结构做计数器,需要和 Redis 有几次交互,单个脚本的处理速度为 0.03M/s (已经优化过了),开 200+ 个进程数据聚合这块应该是抗的住的
    "
    假设 3w 记录 /s , redis 估计也要 10w+的 qps 了。看能不能优化计算流程。
    hanwujibaby
        41
    hanwujibaby  
       2016-03-03 17:44:34 +08:00
    redis 在内存占用率比较高的情况下不太稳定,切到 kafka 之类的,数据的聚合可以在内存中算,不用放到数据库中再聚合。看下 spark 或者 storm 吧。
    9
        42
    9  
       2016-03-03 19:13:36 +08:00
    数据入 es ,用 es 的 api 做统计,统计后的数据入回 mysql ,不要直接入库到 mysql ,这是坑啊
    publicAdmin
        43
    publicAdmin  
       2016-03-03 19:20:48 +08:00
    对的。楼上 @9 的方案和我们之前处理方式一样。 用户打点数据,个人觉得你直接丢 mysql 无形中在给你自己增加压力,入库读库都存在风险,何不如丢类似于 es / hdfs/ influxdb 之类的天生自带索引查询的。
    wusuopuBUPT
        44
    wusuopuBUPT  
       2016-03-03 19:38:15 +08:00
    这种场景已经不适合 mysql 了,我们的数据处理流程是:
    flume 采集->kafka 队列->ETL 清洗->HDFS 存储->Hive 查询->BI 系统
    wusuopuBUPT
        45
    wusuopuBUPT  
       2016-03-03 19:39:57 +08:00
    上面是离线(非实时)的方案, 实时系统也在调研,一般会在 kafka 后面接入 storm/spark 做流式实时计算
    a591826944
        46
    a591826944  
       2016-03-03 19:47:07 +08:00
    之前做过类似的。不过不是日志。。就是用户的点击数据。
    因为是 http 请求。 php 接收 -> rabbitMQ -> storm -> mysql
    每天 3 亿左右 。。没达到你那么高。。。
    RangerWolf
        47
    RangerWolf  
       2016-03-03 21:09:52 +08:00   ❤️ 1
    我这边的解决方案是 Cassandra 集群~ 一开始不熟悉的话在设计表结构上是个大坑
    熟悉之后,还需要配上 Spark 集群来进行计算。 当然两边的配合又是一个大坑
    在搜索的时候,还需要让 Cassandra 加上 lucene 插件,不是官方推荐的 Solr

    想简单可以试试 Cassandra 官网推广的 DSE 。 初创企业(年利润 300M 美刀以内)没有 license 的问题~

    最高试过 3.9W 写请求 /s

    不知道你说的 6M/s 是大小 6MB 还是 600W 的写请求~ 如果是后者,爱莫能助啦~
    chendahui007
        48
    chendahui007  
       2016-03-03 21:31:30 +08:00
    以前搞过 ELK , 之前用 mongo ,也用过 mysql ,都不合适,建议 E 。 E 够强大,适合存储日志,如果用上 kafka ,还可以订阅日志
    tabris17
        49
    tabris17  
       2016-03-03 21:36:03 +08:00
    其实我在想,用 zmq 自己写一个分布式日志处理程序也不是太复杂
    lujiajing1126
        50
    lujiajing1126  
       2016-03-03 21:51:18 +08:00 via iPhone
    elk 。。队列可以选 kafka 。事实查询用 e 。同步写到 hbase 也可以做离线分析。。似乎用 storm 的也有
    xhat
        51
    xhat  
       2016-03-03 23:32:07 +08:00
    为什么没人提到 leveldb ?
    msg7086
        52
    msg7086  
       2016-03-04 02:00:14 +08:00
    1) 换 innodb ,切换成单表单文件模式
    2) 改掉刷日志模式 https://wiki.phoenixlzx.com/page/MySQL
    3) 考虑上混合 SSD 阵列,或者直接上 SSD 。
    zuo
        53
    zuo  
       2016-03-04 02:59:14 +08:00
    既然用上了 logstash 为什么不一步到位 输出到 Elasticsearch ,可以满足你后期的日志查询。做分析可以顺便把日志输出到 hdfs ,然后在结合 spark 或者 hadoop
    cobopanda
        54
    cobopanda  
       2016-03-04 09:27:29 +08:00
    用 ES 试试吧
    firefox12
        55
    firefox12  
       2016-03-04 11:15:51 +08:00
    如果数据库本身不是问题的话, 插入是美问题的。
    但是你 6M/s 按照你的量

    6*3600*24 /1024 每天 500G, 数据库会迅速垮掉 ,完全是个错误的设计。

    如果是在线查 log 的话, es 会好一点。 这种应用用 mysql 去做 并不好,统计应该靠应用去做。
    gushan
        56
    gushan  
       2016-03-08 14:39:47 +08:00
    日志数据直接存储 MySQL 在后期扩展还是有问题的,可以考虑下阿里云日志服务。
    1 )提供了简单接入客户端( https://yq.aliyun.com/articles/3228?spm=5176.team4.teamshow1.37.faH93Z
    2 )日志收集到服务端后提供多种消费方式:数据通道(类 Kafka )/数据投递( ODPS 、 OSS-组合 E-MapReduce Spark )/实时搜索( https://help.aliyun.com/document_detail/sls/user-guide/overview.html
    wujunze
        57
    wujunze  
       2016-06-09 21:06:01 +08:00
    Spark 你值得拥有!
    sumonian
        58
    sumonian  
       2017-12-01 14:09:40 +08:00
    elk 值得你拥有
    jemygraw
        59
    jemygraw  
       2018-07-11 18:51:39 +08:00
    你前端不应该用 redis,应该用 kafka。或者直接用七牛日志平台吧。
    PoetAndPoem
        60
    PoetAndPoem  
       2019-02-20 15:51:07 +08:00
    @xgdyhaiyang 你好,那轮子中文介绍打不开,不知道怎么使用
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3457 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 11:21 · PVG 19:21 · LAX 03:21 · JFK 06:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.