项目经历:基于流式计算的实时日志分析与异常检测系统 1.背景与痛点 那时候公司业务正处于粗放增长期,核心业务就是收单和交易,每天形成的日志量不可想象。我们有个需求是,系统需求把日志流实时压进数据库,然后出个报表。

当时用的方案是先把日志推个 Kafka,再分表,最终用 Spark 取数,最终再用聚合函数算。结局就是,延迟挺高,并且报表出来要几秒到几分钟。 那时候老板要的是“准”,不是“准”。我们赶在双十一之前上线的,那时候我们三个开发人员,天天泡在机房里,盯着监控,盯着日志,盯着报错。有一次大促,系统崩了,日志堆得像一座山,我们社死都没事,关键是业务停摆。

那一刻我才明白,数据慢就是业务停,而慢的根本缘由在于我们的逻辑忒复杂,把好办的东西拆碎了。 2.技术栈 我们最终选定的技术栈实际上就四样:Python、Spark SQL、Flink 和 Redis。

没有别的杂七杂八,就是这四样东西组合起来搞定。 3.项目细节 咱们这个项目,核心目标是解决“实时性”和“准性”的矛盾。 我们的核心思路是,把日志处理改成流式计算。

不需求先把数据存到磁盘再算,直接拉下来,流着算。 数据流速对比 上线前,我们在 Kafka 里存了十年的数据,Spark 跑一次这个报表得 5 分钟。上线后,变成了 Flink 做实时计算,数据压进 Redis 做缓存,算出来的结局延迟只有 200 毫秒。对比一下,这就是质的飞跃。 架构设计 整个链路,日志先进来进 Kafka,然后 Kafka 刷到 Flink 的 Sink 端。Flink 负责做实时计算,把日志分好组,算完把结局写回 Kafka。最终 Kafka 再刷给 Redis,Redis 负责做缓存,算完把结局写回数据库。 数仓逻辑 数仓这块改得最狠。

那会儿我们是用 SQL 写个 Spark 程序,把日志读出来,再算一次。目前改成 Flink 实时计算。Flink 在计算的时候,直接往 Redis 里写数据,Redis 缓存起来,后端查表的时候直接读缓存。 效果验证 上线首周,我们改了这个逻辑,系统的可用性提升了 90%。日志查询的响应工夫从 4 秒直接掉到了 150 毫秒。

更关键的是,日志的准率提升了 15%。

那会儿出于延迟忒高,害得有些边缘案例判断不准,目前流式计算下来,数据是准的。 异常处理 还有一个亮点是异常处理。日志里时常有毛病的记录,比如格式不对要么级别不对的。我们之前用传统方式,把这些错的数据过滤掉,报表就白算了。目前我们改成了,把错的数据直接存到 Redis 的专用标签里,不阻塞主计算逻辑。计算正常,异常数据单独跑一套流程。 日常运维 日常维护这块,也是靠着这套流式架构。

那会儿我们要手动写脚本去查日志,目前变成全自动监控。一旦有任何指标偏离,系统自动报警,直接推送给运维。我们运维团队也不用写脚本管日志了,全靠系统自动告警和调节。 4.挑战与解决 挑战一:高并发下的数据倾斜 大促期间,日志量突增,Flink 侧出现了数据倾斜,局部任务处理极慢,害得 Redis 写入过载。 解决 我们加了 Sharding 分区,把日志按工夫分片,每个分区一个 Task,防止单点过载。

与此同时,我们优化了日志格式,把宽表转成了窄表。最终发现,最大的难题不是计算慢,是数据预处理忒慢。我们把日志解析逻辑拆分成了几个小任务,分别跑在不同的节点,彻底避免了单点瓶颈。 挑战二:实时性与准性的平衡 系统上线后,实时性挺好,但间或出现少量错数据。 解决 这个难题一直困扰我们。我们最初想用 Flink 自带的 Sink 模式,结局发现好办丢数据。

后来我们引入了 Redis 做缓冲,把计算结局先存 Redis 里,等数据跑完再缓存到数据库。别看多了一句代码,但保证了准性。 挑战三:资源消耗难题 早期 Spark 方案别看快,但内存占用极大,单次运行高峰时内存爆了。 解决 我们彻底抛弃了 Spark 全量计算。改用 Flink 流式计算,内存占用下降到了原来的 1/5,并且能够动态调整资源分配。目前系统能够稳定跑得更久,资源利用效率更高。 5.成果 这个项目上线后,我们跑了大量类似的案例。

不管是报表生成,还是实时监控,这套流式架构都能跑通。 在上线首季度,我们节省了 40% 的运维资源。日志查询延迟下降了 95%,系统可用性达到了 99.99%。

更关键的是,这套架构为公司后续扩展打下了基础。目前 new project 进来,我们套用这套逻辑,半天就能跑通,效率比年初提升了 3 倍。 我认定真正的技术,不是堆砌多高的架子,而是如何把数据流得更顺,让业务跑得更快。

这个项目标核心,就是“流”和“准”。目前回头看,这套逻辑别看改了大量遍,但核心思想没变,就是好办直接,把复杂的难题拆解成一个个小步骤,一个个小步骤跑通了,整个难题自然就解决了。 6.总结 这次经历让我意识到,有时候最好的方案不是最复杂的,而是最顺的。咱们这个项目,没有那些花哨的框架,就是好办的 Spark、Flink 和 Redis 组合,但处理起来却异常平滑。 当时我们三个开发人员,天天泡在机房,盯着监控,盯着日志,盯着报错。有一次大促,系统崩了,日志堆得像一座山,我们社死都没事,关键是业务停摆。

那一刻我才明白,数据慢就是业务停,而慢的根本缘由在于我们的逻辑忒复杂,把好办的东西拆碎了。 目前系统运行平稳,日志查询延迟低,准性高,运维自动化程度也极高。

这套架构不仅解决了当时的痛点,也为后续业务扩展供给了坚实的基础。

这套逻辑已经跑了大量类似的案例,不管是报表生成,还是实时监控,都能跑通。 结论就是:这套逻辑别看改了大量遍,但核心思想没变,就是好办直接,把复杂的难题拆解成一个个小步骤,一个个小步骤跑通了,整个难题自然就解决了。 7.自我评价 总结一下,这个项目最大的收获有两点: 第一,我学会了用流式计算代替传统的批量处理。

那会儿我认定批量处理就够了,实际上在高并发场景下,流式计算能节省大量的 IO,并且能实现真正的实时反馈。

这在业务驱动的场景里,意义庞大。 第二,我学会了在“实时性”和“准性”之间做权衡。

有时候务必牺牲一点实时性来换取准性,有时候务必牺牲一点准性来换取实时性。

没有绝对的最好,只有最合适的。

这次项目里,我们最终选择了以准性为优先,出于数据不准,业务就无法交付。 这次经历让我对代码底层的理解加深了大量。

那会儿我只关切功能是否实现,目前更关切数据流的走向,关切各个环节的损耗和延迟。

这种思维方式的转变,对我的后续工作帮助贼大。 自然,这次项目也有一些教训。

比如初期对 Flink 的参数调优不够,害得运行初期稳定性不稳定。

后来我们慢慢摸索,积少成多,最终找到了一个最佳配置区间。

这说明,调试是一个反复的过程,没有捷径。 总的来说,这个项目别看不算特别宏大,但它是当时公司业务转型的关键一步。它让我明白了,好的架构不是高大上,而是能帮大家把事做得更快、更稳、更准。