素材牛VIP会员
海量日志数据如何处理统计?
 zh***ao  分类:SQL代码  人气:975  回帖:4  发布于6年前 收藏

项目需要做一个dashboard图表网站,展示日志的相关统计信息。这个页面图表很多,一次性会加载出很多数据。

日志表有很多种,都是一些入侵攻击日志、恶意站点访问日志等等,需要统计出当前时间、过去24小时、过去一周被攻击主机个数、恶意站点数(这是其中两个需求)等等数据。

比如被攻击主机个数,需要查多张数据表,然后统计出这个数据。

日志存储在PostgreSQL里面,已经基于时间做了分表,但是每天的的日志量都在100W以上。

写入数据库的模式是随时从其他的系统中写入。

根据这个应用场景,如果设计这个后端统计呢?还请大神提供一点思路,谢谢。

讨论这个帖子(4)垃圾回帖将一律封号处理……

Lv4 码徒
go***le 学生 6年前#1

虽然是一个PostgreSQL的问题,但是打了各种数据库标签。那么我就从MongoDB和NoSQL的角度说说这个问题。因为一些情况不是特别清楚,基于自己的假设来回答,如果有和你情况不符的地方再提出来。
数据库的日常应用无非OLAP和OLTP两大类,你的应用是一个比较典型的OLAP应用。通常OLAP的特点是对时效性的要求不是非常高,对系统资源占用比较重。你没有提对时效性要求到底有多高,还有你们数据的写入模式是怎样的。每天某个时间批量导入?或是随时从其他系统写入?不管怎样,还是有一些通用的办法来应对的。以下是无论使用哪种数据库都可以做的一些事情:

预聚合

从你的描述来看这是个比较典型的时序数据,过去的数据是不会变的。所以可以在每天结束时把这一天的数据先聚合好,某年某月某日有多少次攻击多少次恶意访问之类。如果要查一段时间的,则可以把已经按天统计好的数据再聚合一次。比如一个月的就是30条数据再次聚合,这比30x100w=3000w条数据的聚合要轻松很多。如果你的统计粒度需要比天还小,那就要看具体小到什么程度。如果是精确到时,那我可能还是会考虑按小时预聚合,这样统计比如过去30天的数据,就会有30x24=720条数据,也在接受范围内。但是如果统计范围允许到年,则有365x24=8760,情况就不是很乐观了。当然如果需要精确到分钟,那又是更麻烦的事情。但即使这样,预聚合仍然能有效减少数据量从而降低运算所需的时间和资源。为了解决小粒度聚合的问题,实际应用中可能需要进行多个层次的预聚合。比如按月,按天,按时,按分分别聚合好,这样在需要某分钟到某分钟的数据时,可以把大粒度的范围通过月、天、时先消化掉,剩下的两头零碎部分再用时、分钟处理,这样最大程度上减小需要聚合的数据量。

索引优化

无论使用哪种数据库,索引优化都是很重要的步骤。按上述方法预聚合后,各种时间因素肯定都是需要在索引中的。如果在时间基础上还需要对某个主机或域名等筛选,则最好是有这些字段的联合索引。具体问题具体分析,这个还需要你根据自己的表结构和查询去优化。

读写分离

无论怎么优化,OLAP对资源的占用都是不能忽略的。如果你的数据是实时写入,聚合期间很容易受到I/O瓶颈的影响。所以最好是把接受数据和分析数据的结点分开。

安利时间

说说如果使用MongoDB还有哪些事情可以做。

  1. 分片。水平扩展是NoSQL的特色之一,理论上所需时间和结点数量成反比。而数据量的增长在分布式环境中也不是一个问题。

  2. Tag Aware Sharding。MongoDB分片的特色,可以把旧数据自动归集到容量大,但是性能相对差的硬件上,这样让热数据始终保持在性能较好的机器上达到更好的效果。

  3. 天然的读写分离和高可用。复制集本身就可以实现读写分离和高可用。相信这两个特性对任何应用都是很有意义的。

最后还是要提醒一点,理论归理论,没有一个方案是完美的,实际应用时肯定还会遇到各种各样奇怪的问题。编程是一项创造性的工作,需要你自己在实践中不断寻找最优的解决方案,在实践中成长。

Lv3 码奴
二***了 交互设计师 6年前#2

没做过,觉得可以用定时器然放到redis里,现查的话确实太慢。多个查询条件都加上索引会好些吧

Lv3 码奴
Go***ng 职业无 6年前#3

这个日志数据处理是主业还是副业?

如果是主业,那就要学习下 @Mongoing中文社区 的方案,尤其是时序数据进行预处理的概念。

如果是副业,那直接上 ELK 套件就好了,投入低见效快。

Lv5 码农
疯***斯 职业无 6年前#4

1、个人感觉按天分区比较好,为了提升性能,统计SQL不要直接查询父表,而是将子表进行 union 统计。
2、另一点是合理设计索引;

 文明上网,理性发言!   😉 阿里云幸运券,戳我领取