• 请不要在回答技术问题时复制粘贴 AI 生成的内容
iyaozhen
V2EX  ›  程序员

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

  •  
  •   iyaozhen ·
    iyaozhen · Mar 3, 2016 · 19279 views
    This topic created in 3744 days ago, the information mentioned may be changed or developed.

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

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

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

    https://github.com/haipome/logdb

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

    用的 ELK

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

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

    现在系统没啥压力.

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

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

    最高试过 3.9W 写请求 /s

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

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

    如果是在线查 log 的话, es 会好一点。 这种应用用 mysql 去做 并不好,统计应该靠应用去做。
    gushan
        56
    gushan  
       Mar 8, 2016
    日志数据直接存储 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  
       Jun 9, 2016
    Spark 你值得拥有!
    sumonian
        58
    sumonian  
       Dec 1, 2017
    elk 值得你拥有
    jemygraw
        59
    jemygraw  
       Jul 11, 2018
    你前端不应该用 redis,应该用 kafka。或者直接用七牛日志平台吧。
    PoetAndPoem
        60
    PoetAndPoem  
       Feb 20, 2019
    @xgdyhaiyang 你好,那轮子中文介绍打不开,不知道怎么使用
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   946 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 94ms · UTC 20:36 · PVG 04:36 · LAX 13:36 · JFK 16:36
    ♥ Do have faith in what you're doing.