> 技术文档 > 从困惑到理解:从储存ES到引入Hadoop处理日志数据

从困惑到理解:从储存ES到引入Hadoop处理日志数据


从困惑到理解:从储存ES到引入Hadoop处理日志数据

前言

不知不觉已经上班了一年,在这一年里,我总是习惯于按照 leader 的要求,学习指定的技术并实现相应功能。很多时候,我并不清楚为什么要选用这些技术,总觉得其他技术也能完成任务,但为了学习和完成工作,我还是会按照 leader 的指示去做。
最近在项目中,就遇到了这样的情况。原本运行良好的系统,leader 突然提出要将生成日志数据的储存由原本的ES,转移接入公司的大数据平台 Hadoop。Hadoop 的学习成本可不低,而且从初步接触这一个月来看,数据的存储和读取速度远不如之前快。
不过,在向组里的资深同事请教,并自己上服务器对过往日志数据进行统计分析后,我逐渐明白了引入 Hadoop 的必要性。虽然短期内开发成本有所增加,效率也不如之前高,但从长远来看,这是有利于系统扩展的。

一、项目背景

这个项目其实就是对公司内部涉密系统进行实时监控,负责对内部涉密系统操作日志的采集,通过计算分析原始日志,生成可视化报表并实时监控异常行为,及时通过邮件告警相关人员,确保涉密系统安全运行。

1. 前期情况

在项目前期,我们接入了一个公司内部系统,每天生成的日志数据量大约为1.2GB(每天往ES写入了约20w条数据)。经过内部逻辑计算拆分后,又会生成2-3GB的结果数据,即一个系统每天总共产生3~4GB(约80万到90万条数据)的日志数据,这些数据存储在ES中,通过ELK Stack实现日志的收集、存储和可视化展示。这种方案在之前运行得还算不错。

原始日志收集是使用的ELK Stack:1) 在系统上通过AOP生成的自定义日志;@Aspect@Componentpublic class LoggingAspect { private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class); @Around(\"execution(* com.example.service.*.*(..))\") public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable { long startTime = System.currentTimeMillis(); // 获取方法的签名和参数 MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); String methodName = methodSignature.getMethod().getName(); Object[] args = joinPoint.getArgs(); // 记录方法调用前的日志 logger.info(\"Before method: {} with arguments: {}\", methodName, Arrays.toString(args)); // 执行目标方法 Object result = joinPoint.proceed(); // 记录方法调用后的日志 long timeTaken = System.currentTimeMillis() - startTime; logger.info(\"After method: {} with result: {} and time taken: {} ms\", methodName, result, timeTaken); return result; }}2) Filebeat收集日志;(其实就是读取一些配置而已)filebeat.inputs:- type: log enabled: true paths: - /var/log/app/user-operations.log - // 发送到Logstash:output.logstash: hosts: [\"logstash-server:5044\"] 3) Logstash处理日志;// 使用grok过滤器解析日志字段filter { grok { match => { \"message\" => \"用户ID:%{NUMBER:user_id}, 操作时间:%{TIMESTAMP_ISO8601:operation_time}, 操作类型:%{WORD:operation_type}\" } }}// 将处理后的日志发送到Elasticsearch:output { elasticsearch { hosts => [\"elasticsearch-server:9200\"] index => \"user-operations-%{+YYYY.MM.dd}\" }}4) ES存储日志;(在上学时候了解ES都是通过hm,ssg的电商项目,主要用于全文搜索引擎,模糊查询和排序,而实际上不仅仅只有这种应用场景,ES常用于收集、存储和分析日志数据,配合LogstashKibana(ELK栈)实现强大的日志分析系统;而且ES可以实时处理和分析大量数据,可以存储和分析结构化和半结构化数据,我做过对比测试,把每天生成的几十w条数据存放至mongoDB确实会比ES查询得慢得多)5) Kibana可视化日志;Kibana是一个开源的分析和可视化平台,常用于Elasticsearch的数据展示平台。使用Kibana的可视化工具(如柱状图、折线图、地图等)可以展示和分析操作日志。

2. 现状

当然,开发这个系统不可能只为了一个系统而服务,随着业务的扩展,我们接入了三个内部涉密系统,每天生成的日志数据量飙升至10多GB。虽然ES通过设置分片数据还能勉强应对,但已经感受到了压力。如果继续按照这种模式发展,未来可能会面临更大的挑战。

// 这个过程中了解到了ES的一些相关参数的配置,即主分片数和副分片数1.主分片是索引数据的实际存储单元,每个索引的数据会被分配到主分片中。在查询相关资料后,得出的大概结论(当然得根据实际来)数据量较小的索引:如果索引的数据量较小(例如,只有几百MB到几GB),可以将主分片数量设置为13个;数据量较大的索引:对于数据量较大的索引(例如,几十GB到TB级别),建议将主分片数量设置为520个;具体数量取决于集群的硬件资源和查询性能需求。2.副本分片是主分片的副本,用于提高数据的可用性和查询性能。每个主分片的数据会被复制到副本分片上,即如果主分片数为 2,副本分片数为 3,则索引的总分片数为:主分片数:2副本分片数:2 × 3 = 6总分片数:2 + 6 = 8每个主分片(2 个)会存储一部分数据。每个主分片会被复制到 3 个副本分片上。因此,每条数据会被存储在 1 个主分片和 3 个副本分片上,总共 4 份。索引的总存储空间会是主分片数据量的 4 倍(1 主分片 + 3 副本分片)。3.随着时间推移日志数据量会不断增加。为了更好地管理数据,项目中使用索引生命周期管理(Index Lifecycle Management, ILM)// ILM策略示例:每天创建一个新的索引,例如log_index-2025-05-08。PUT /_index_template/log_index_template{ \"index_patterns\": [\"log_index-*\"], \"template\": { \"settings\": { \"number_of_shards\": 3, \"number_of_replicas\": 1 } }}使用ILM策略管理日志数据,根据数据的活跃度和时间自动调整索引的状态。

3. 未来展望

公司有近百个内部系统,虽然有些系统的访问量大,有些小,但如果后续都接入日志收集,每天生成的日志量将会非常惊人,可能会达到几百GB甚至1TB以上。在这种情况下,继续使用ES来存储和处理日志数据显然是不可持续的。于是,我们将目光转向了公司的大数据平台Hadoop。

二、为什么选择Hadoop

虽然Hadoop不是我们小组搭建的,公司里早已搭建好了Hadoop大数据平台,但从网上也查询到了Hadoop的使用优势:

1. 扩展性

Hadoop是一个分布式存储和计算框架,具有强大的扩展性。它可以轻松地通过增加节点来应对数据量的增长,而不需要对现有系统进行大规模的改造。这对于未来可能不断增加的日志数据量来说,是一个非常重要的优势。(Hadoop的横向扩展能力(scale-out)是其应对大数据量的关键特性之一,通过增加节点数量来提升存储和计算能力。

2. 成本效益

虽然引入Hadoop会增加一定的开发成本和学习成本,但从长远来看,它可以帮助我们更好地管理和分析海量的日志数据,提高系统的整体性能和稳定性。而且,Hadoop的开源特性也使得我们在使用过程中可以灵活地进行定制和优化,进一步降低使用成本。

3. 数据处理能力

Hadoop的MapReduce编程模型可以高效地处理大规模数据集,通过将任务分解为多个子任务并并行执行,大大提高了数据处理的速度。此外,Hadoop还提供了丰富的数据处理工具和框架,如Hive、Impala等,可以方便地对日志数据进行复杂的分析和挖掘。

// 这些数据处理工具简直就是我们的救星,让我们在Hadoop的使用过程中又变回了SQL boy我们在java代码中使用Impala操作Hadoop中的日志数据,Impala是一个开源的分布式SQL查询引擎,它可以直接在Hadoop的数据存储上运行,提供快速的交互式查询能力。

4. 数据存储

Hadoop平台使用HDFS来存储日志数据。HDFS是一个分布式文件系统,具有高容错性和高吞吐量的特点。它可以将大文件分割成多个块(默认128MB),并将这些块分布存储在不同的节点上,从而提高数据的可靠性和读写性能。

特性 ELK Stack Hadoop 查询速度 适合中小规模数据,查询速度快,实时性高 适合大规模数据,查询速度随着数据量增加而降低,但可以通过优化(如使用Impala)提升 存储成本 存储成本较高,尤其是数据量大时 存储成本较低,适合海量数据存储,且硬件成本可控 扩展性 扩展性有限,主要通过增加硬件资源(如内存、CPU)来提升性能,但成本较高,且集群规模扩大时管理复杂度增加 扩展性强,通过增加节点即可轻松扩展存储和计算能力,支持横向扩展(scale-out),适合处理不断增长的数据量 数据处理能力 适合实时分析和小规模数据处理,对大规模复杂数据处理能力有限 适合大规模数据的离线处理和复杂分析,MapReduce模型可高效处理海量数据 可靠性 数据存储在Elasticsearch中,可靠性较高,但副本机制可能导致存储空间占用较大 HDFS具有高容错性,通过数据块的多副本机制确保数据可靠性,即使部分节点故障也不会丢失数据

三、总结

通过真实的项目实践,我深刻体会到了Hadoop在处理海量日志数据方面的优势。虽然在引入Hadoop的过程中遇到了一些困难,但随着对它的深入了解和使用,我逐渐认识到对于这个项目而言,Hadoop不仅可以帮助我们更好地应对数据量的增长,还可以为数据分析和挖掘提供更强大的支持。

在未来的工作中,我将继续学习和探索Hadoop及相关技术,进一步提升自己的技术水平,为项目的成功贡献更多的力量。同时,我也希望这篇文章能够对那些正在面临类似困惑的开发者有所帮助,让大家能够更加清晰地认识到Hadoop的价值和应用场景。

【本人工作一年,项目中刚接触Hadoop,若文章中有什么错误还请指正】