一、背景

支付中心作为携程集团公共部门,主要负责的业务包括交易、实名绑卡、账户、收单等,由于涉及到交易相关的资金流转以及用户实名认证,部分用户操作环节的中间数据应内控/审计要求需要长时间保存。当前研发应用多,日志量大、格式各异,对于日志的存储和使用产生较大的挑战,故支付数据与研发团队群策群力,共同开发了一套统一日志框架。

二、总体架构图

核心模块包括:日志生产、日志采集、日志解析,其中调用流程如下:

1)研发应用/服务接入基于log4j2扩展的统一日志组件,将日志抛送至kafka。

2)周期性启动消费kafka topic的camus job将日志写入hdfs。

3)T+1启动MR job读取camus写入的hdfs内容并load到hive表。

三、日志生产-统一日志组件

支付研发基于log4j2自定义了多个Appender,将应用日志以服务调用形式抛送至kafka,并被log_process_service 服务统一处理并提交至携程常用基础日志框架如:CLOG、CAT、ES,各应用无需关心公司日志框架,统一由日志平台处理。

其优点:

  • 不同日志框架对应着不同的Appender,方便进行日志框架接入的扩展。
  • 采用AOP编程,对于接入的业务侵入性小,接入简单。
  • 定义了丰富的java注解,便于日志配置化输出,其中可打印日志包括但不限于:类名、方法名、方法入参、返回值、异常等,支持敏感字段脱敏。

存在的问题:

  • 日志格式不规范:研发应用数百个,研发人员较多,日志格式差异大,给数据分析和使用带来巨大挑战。
  • 存储时长短:当前公司在线CLOG存储系统只能查询最近几天数据、ES保存稍长一段时间数据且不支持批量查询,基础离线CLOG hive表由于数据量巨大,仅能做到T+2,无法满足T+1的报表需求。

故支付数据团队在研发团队统一日志组件的基础上,结合数据分析和数据存储生命周期开发了统一日志框架。

3.1 统一日志-埋点设计

支付研发团队负责数百个服务或应用,支持的业务包括:路由、鉴权、免密、卡服务、订单、钱包实名、电子支付等,不同的业务又可拆分app、h5、online、offline等项目,整合这些数据是个极大的挑战。如果各系统研发埋点任意指定,会给BI数据分析带来极大的困难,数据分析准确性难以得到保障,故支付数据基于业务特点定义了一套统一日志埋点规范。

字段定义主要是基于日常分析需求,致力于简化数据的使用,故总体原则为json形式,当前原始日志有两部分组成:tag/message,其中tag数据结构为Map,关键数据一般是通过tag内的数据进行检索,明细数据通过message进行检索,tag与message的组成格式为:[[$tag]]$message,目前标准字段包括两类:规范性字段和通用性字段。

3.1.1 规范性字段格式

规范性字段需要应用研发一定程度的参与,提供符合字段命名的类和方法。部分字段名称及定义如下:

其中tag可以灵活填充,主要扩展字段如下:

3.1.2 通用字段格式

日志框架能够自动获取属性,无需研发编码,即可打印。

3.2 分区/分桶字段的定义

当前离线数据分析基于hive引擎,hive的分区分桶设计极大的影响了查询性能,特别是在日志量巨大的场景下,分区字段的选择尤为关键。如:用户进入支付收银台可能会有上百个场景,而每种场景下会有多次服务调用,其中不同场景下服务调用频率差异很大,占用的空间差异也较大,故针对每种场景分配一个唯一的场景号,通过场景号进行分区,可以高效的进行数据分析,而过多的分区也可能导致较多的小文件,对hadoop namenode产生较大的影响,此时结合分桶能够达到优化查询效率且避免分区无限制野蛮增长产生众多过多小文件的问题。

四、日志采集

日志采集框架基于LinkedIn的开源项目Camus,Camus使用MapReduce读取kafka数据然后写入hdfs,由于无reduce阶端,所有数据处理及写入都在Map侧,很少会发生数据倾斜,Camus具有接入简单,方便扩展,故我们进行了二次开发,以满足当前业务的需要:

  • 自定义decoder/partitioner,原生的decoder/partitioner支持的hdfs落地路径主要基于日期,较为粗糙,无法适应业务的需要。故自定义decoder 抽取原始日志分区字段,然后代入partitioner中,生成具有业务含义的hdfs输出路径,为特定时间范围数据回刷提供了高效的解决方案。
  • 自定义provider,原生的StringRecordWriterProver仅支持text文件方式落地,占用空间大、压缩后无法并行切分,容易错列错行,而orc格式数据,有效的节约了hdfs占用空间,查询效率高且可以切分,有利于日志解析job的高效执行。其中在配置Camus job过程中需要关注如下问题:

4.1 camus 任务执行

  • 执行频率设置
Error: java.io.IOException: target exists.the file size(614490 vs 616553) is not the same.

由于kafka消息保存天数有限和单个分区size有限(Server 配置:log.retention.bytes),携程侧为3天和10G,如果camus同步kafka频率较低时,可能会出现数据丢失,故需要根据日志量大小,设置camus 调度任务的执行频率,防止数据丢失。

  • 任务重叠执行
Error: java.io.IOException: target exists.the file size(614490 vs 616553) is not the same.

camus从kafka 读取数据,任务要以单例形式执行,任务执行完成后才会更新kafka的offset,若一个任务执行了多次,就会导致数据大小无法对齐,此时需要删除配置路径下的所有数据后重新启动任务,即可完成修复。

4.2 如何控制camus落地文件的大小

当kafka各partition数据写入量不平衡时,由于各partition会写入一个hdfs文件中,如果研发日志集中写入kafka某个partition,会导致这个partition对应的hdfs文件占用空间特别大,如果恰巧这个文件是不可切分的,极端情况下会导致只有一个线程去解析这个大文件,降低了数据读写的并发度,拉长了数据解析时间,遇到这种问题的解决办法是:

  • 临时解决方案:研发日志分散写入kafka partition,不要导致某类数据集中写入一个partition;
  • 高效解决方案:数据侧采用可切分的输入格式,进行数据切分;

4.3 写入orc文件格式注意事项

  • orc写入timeout
AttemptID:attempt_1587545556983_2611216_m_000001_0 Timed out after 600 secs

orc文件写入速度较text文件会慢很多,如果同时写入的的文件较多或者内存回收占用时间较长,会导致map方法在600秒内没有读、写或状态更新,job会被尝试终结,解决方法是调高默认的task超时时间,由10分钟调高到20分钟。

mapreduce.task.timeout=1200000

  • OOM 内存溢出
beyond physical memory limits. Current usage: 2.5 GB of 2.5 GB physical memory used; 4.2 GB of 5.3 GB virtual memory used. Killing container.

在orc写文件的时候如果出行较多的OOM,此时需要加大map执行的内存。

mapreduce.map.memory.mb=8096
mapreduce.map.java.opts=-Xmx6000m

五、统一日志-解析

鉴于日志解析工作主要集中在MapReduce的Map侧,而Map侧通过参数调整能够很容易控制map的个数,以提高数据解析的并发度,MapReduce主要分为:intputformat、map、shuffle、reduce等几个核心阶段,通过优化各阶段的执行时间,可以显著提高日志解析的速度。

5.1 inputsplit优化

MR job中影响map的个数主要有:

  • 文件个数:如果不采用CombineFileInputFormat,那么不会进行小文件合并,每个文件至少有一个map处理,当小文件太多时,频繁启动和回收线程也会对性能产生影响,同时对集群其它job资源分配产生影响。
  • 文件属性:当文件较大且可切分时,系统会生成多个map处理大文件,inputsplit块按照MR最小单元进行文件切割(split),并且一个split对应一个MapTask。

前期日志解析程序的性能较高,一天的全量日志解析约25分钟,中间有段时间任务执行时间从25分钟延迟到4个小时,原因是研发将大量订单号为空的日志写入到指定的partition中,日志量巨大,导致其中少量map在读取大文件时执行时间特别长。

经过分析发现text+snappy 文件无法切分,只能够被一个map处理,将camus落地数据格式从text+snappy换为orc+snappy格式,同时开发了支持orc文件格式的CombineFileInputFormat,既减少了小文件对hadoop计算资源果断的占用也提高了job的并发程度。

5.2 shuffle优化

使map的输出能够更加均匀的映射到reduce侧,由于默认的分区策略是对map的输出key hash取reduce个数的模,容易导致数据倾斜,解决办法是在key上面增加时间戳或者重写partition函数。

5.3 批量日志解析

当前MR的输出会作为hive外表的数据源,hive表会按照业务过程进行分区,所有数据的解析结果路径为:日期+业务过程,而业务过程可能有数百个,采用了MultipleInputs/MultipleOutputs 能够在一个mapreduce job中实现多输入多输出的功能,以适应业务自定义解析,并归一化后统一抛到reduce侧。

5.3.1 空文件生产

在使用的过程中会出现生成众多临时小文件及生成size 为0的小文件,增加了hdfs namenode内存压力,同时空文件也会导致spark表查询失败,可通过LazyOutputFormat进行修复。

5.3.2 文件重复创建

MultipleOutputs输出文件一般以name-r-nnnnn的格式进行命名,其中name与程序指定的文件名有关,nnnnn表示reduce任务号。在处理数据较多时,可能会存在reduce侧反复创建已存在的文件,导致任务长时间运行而不能成功,中间生成了大量小文件,对hadoop namenode产生较大压力,影响整个集群响应时间。

解决方案为:在reduce侧进行数据写入时,需要对exception进行捕捉,一旦出现数据写入exception,即将对应的写入reduce文件删除并终止程序,由于MR支持高可用,当一个reduce taks 失败后会自动重试,重试一定次数依然不能够成功就会导致整个任务失败,每次重试避免了不停的重复创建已存在的文件,引起NN响应时间极速下降。

5.4 reduce个数调整

目前日志解析的reduce侧主要用于orc数据写入,当reduce个数较少时,会导致reduce内存溢出,而reduce个数较多时,可能会导致非常多的小文件且占用集群过多资源,可以通过计算map侧输入文件的个数及总占用空间,动态计算需要的reduce个数,以达到合理利用资源的目的。

六、日志治理

日志落地导致的一个问题是存储空间增长迅速,当前支付中心日均新增ORC压缩原始数据量TB级别且还在持续增长中。

支付数据侧根据研发、产品的需求对不同类型日志进行分级,对于不同类别的日志设置不同的存储周期,主要划分为:研发排障日志、审计日志、数据分析日志等;同时在camus将日志写入hdfs时,由于按照业务分区进行落地,导致生成了大量小文件,需要对这些小文件进行合并并且设置TTL,避免对hadoop namenode产生较大的影响。

七、总结与展望

目前日均TB级数据解析时间在30分钟内完成,后期计划将日志系统导入clickhouse等对实时要求高的场景共运营使用,以支持业务精细化运营和分析。

【作者简介】英明,携程数据研发专家,负责支付离线数据仓库建设及BI业务需求,对并行计算、大数据处理及建模等有浓厚兴趣。

更多携程技术人一手干货文章,请关注“携程技术”微信公众号。

hive 查看 job 日志_日均TB级数据,携程支付统一日志框架相关推荐

  1. logstash 日志_面试和书评:LogStash书,使日志管理变得容易

    logstash 日志 James Turnbull通过解释LogStash在日志项目上下文中的实现细节,为使用LogStash集中日志提供了令人信服的案例. < Logstash手册>通 ...

  2. ios 打印 详细错误日志_【专家专栏】林相宇 | IOS错误日志抓取和分析

    原标题:[专家专栏]林相宇 | IOS错误日志抓取和分析 在调试自己和别人的IOS App时,发生Crash是非常正常的情况,分析这些Crash的主要手段之一就是分析Crash发生时产生的错误日志.对 ...

  3. spring cloud 日志_微服务架构开发实战:ElasticStack实现日志集中化

    常见日志集中化的实现方式 有许多现成的可用于实现集中式日志记录的解决方案,它们使用不同的方法.体系结构和技术.理解所需的功能并选择满足需求的正确解决方案非常重要. 日志托运 有一些日志托运组件可以与其 ...

  4. 手机信令数据怎么获得_聚焦手机信令数据支持城镇体系规划的技术框架

    导读 手机信令数据有效弥补了传统静态数据的不足,能作为城镇体系规划的基础数据之一.本文以手机信令数据获取的城镇联系度为基础,提出城镇体系规划中的空间结构.等级结构.中心城市腹地.区域重要交通设施服务范 ...

  5. 查看电脑重启日志_系统日志看硬盘故障图文教程,电脑日志查看磁盘硬盘坏道问题方法...

    大家好,我是老盖,感谢观看本篇文章,本文做的也有视频,也可以看我发布的视频. 今天和大家讲一下通过电脑的系统日志,判断硬盘是否有问题的一个方法,最近这几天我这个电脑偶尔会卡一下,有的时候还会蓝屏,判断 ...

  6. binlog日志_【删库跑路】使用Binlog日志恢复误删的MySQL数据

    前言 "删库跑路"是程序员经常谈起的话题,今天,我就要教大家如何删!库!跑!路! 开个玩笑,今天文章的主题是如何使用Mysql内置的Binlog日志对误删的数据进行恢复,读完本文, ...

  7. 一行代码,Pandas秒变分布式,快速处理TB级数据

    夏乙 发自 凹非寺 量子位 出品 | 公众号 QbitAI 刚刚在Pandas上为十几KB的数据做好了测试写好了处理脚本,上百TB的同类大型数据集摆到了面前.这时候,你可能面临着一个两难的选择: 继续 ...

  8. 奥维查看行政边界_全国乡镇行政区划数据乡镇边界数据查询获取方式

    原标题:全国乡镇行政区划数据乡镇边界数据查询获取方式 北京揽宇方圆信息技术有限公司提供全国遥感影像数据,全国乡镇行政区划数据,是结合野外实测资料,同时参照有关地理图件,采用人机交互的方式开展行政区划地 ...

  9. 更新日志_面向2021:知客CRM2020年更新日志

    即将与2020年握手道别,我们马上就要推开2021这扇大门.时间不允许我们停留,我们的行动化为不眠的字节,以此来积极回应和融入这滚滚的企业数字化潮流.我们身上背着行囊,其中,有您丰厚的馈赠.我们和您一 ...

最新文章

  1. 一个小小的AI训练营竟然卧虎藏龙
  2. Upgrade after a crash is not supported. The redo log was created with Maria的解决办法
  3. 高昆仑大数定律 中心极限定理
  4. 阿里云DDoS高防 - 访问与攻击日志实时分析(二)
  5. oracle常用sql命令
  6. USCAO Job Processing 4.2(贪心,不知道叫啥方法)
  7. 编程小白的第一本python入门书-《编程小白的第一本Python入门书》读书笔记
  8. 阅读架构漫谈(三)笔记
  9. 比赛结果预测_决策树_随机森林(通用 数据挖掘入门与实践-实验5)
  10. shell脚本执行返回的状态码
  11. 面向对象三个特征总结
  12. linux路由信息预览为空,route - 显示并设置Linux中静态路由表
  13. python随机读取字符_利用python3随机生成中文字符的实现方法
  14. mysql全局变量和局部变量的区别_详细讲解mysql全局变量与局部变量
  15. 实体(Entity)和模型(Model)
  16. 计算机视觉CV:图像处理面试题
  17. python中for循环遍历文件_Python中的用for,while循环遍历文件实例
  18. ColorUI从0开始搭建项目
  19. Python数据分析(4):jieba分词详解
  20. 自用PHP版H5微信公众号吸粉引流的恶搞小游戏 当天收获500+粉丝

热门文章

  1. 【记录贴】cs231n课程作业一遇到问题总结
  2. Leetcode每日一题:559.maximum-depth-of-n-ary-tree(N叉树的最大深度)
  3. TensorFlow2.0:单层感知机梯度计算
  4. 三种代理服务器以及反向代理详解
  5. 飞利浦医疗收购Direct Radiology,加强远程放射学服务能力
  6. 电脑控制手机屏幕软件_手机屏幕如何投屏到电脑
  7. python获取磁盘剩余空间的方法
  8. java sqlserver 遍历_mysql和sqlserver循环插入数据
  9. js 中的switch
  10. [Ext JS4系列]Ext JS4 入门