Skip to content

Latest commit

 

History

History
78 lines (38 loc) · 6.52 KB

日志服务性能优化方案.md

File metadata and controls

78 lines (38 loc) · 6.52 KB

日志服务性能优化方案

1 案例背景

日志服务是新技术体系下核心服务的一部分,主要功能是收集组件日志,提供日志检索和日志分析功能。在项目测试和试点过程中,发现日志服务存在性能问题,主要体现在日志量大时,日志服务存储日志占用大量磁盘IO,导致整个系统变卡。另外按照日志服务的性能规格,能够存储最多1亿条日志数据,需要约300G硬盘空间。在联调环境和硬件受限的测试环境中,出现了多次日志数据占满硬盘的问题,阻塞了调试和测试。本方案记录了日志服务解决上述问题的思路和方法,

2 IO优化方案

为了控制日志服务的IO占用,进行了如下几项优化。

2.1 优化表结构

根据日志规范,一条系统日志分为日志时间(d_timestamp)级别(c_level)模块(c_module)线程号(c_thread_no)代码行(c_source)错误码(c_error_code)和日志详情(c_message)几部分。原表结构将字段分别保存在对应字段中,并且为了实现日志的全文检索,将日志原文又存储在tsv_log字段中。

图1 原表结构

​ 原表结构的好处是支持对日志字段进行精确检索和全文检索,副作用是日志的内容被存储了两份,入库时对IO消耗较大。

​ 考虑到实际使用时的检索条件数量有限(图2),对原表进行了精简。精简后的表结构(图3)去除了线程号、代码行、日志详情三个字段,其中日志详情是系统日志内容最多的字段。根据测试,优化后的表结构存储相同数量的日志,存储空间减小30%

图2 系统日志检索条件

图3 精简后的表结构

2.2 系统日志分区优化

​ 为了实现按组件快速查询日志,对日志表进行了两级分区,第一级是组件分区,即每个组件产生一张日志表;第二级是时间分区,即每个组件每天产生一张日志表

图4 日志两级分区

     对于日志量大的组件(每天百万条),按天分区可以加速查询效率,但对于日志量小的组件,按天分区的加速效果并不明显,并且过多分区将产生文件碎片,进一步降低入库性能。

     考虑到特定项目中,日志量大的组件是固定的几个,可以将分区策略做进一步优化。优化思路是针对日志量大的组件采用按天分区,对应其他组件只按组件分区即可。

2.3 入库性能削峰

为了提高入库效率,日志服务采用批量入库,每次提交500条日志。经过测试,单线程时,入库性能约为1000条/秒。在实际环境中进行测试,优化前的日志服务以最大性能进行写入日志时,系统会间歇性出现卡顿的情况,此时磁盘平均吞吐量达到 16.8M/s。

经过对业务场景的分析,发现组件日志打印越多,业务越是繁忙,在硬件资源有限的情况下,应优先保证业务组件的正常运行。也就是说,日志服务的入库性能应随着日志量的增加而减低。基于这个思路,对日志服务的性能进行了约束。

按照日志服务的性能规格,每天需支持1200万日志入库,平均每秒入库140条。在满足该性能指标的基础上,日志服务对性能做出限制,将入库性能约束为最大200条每秒

对于业务高峰期,日志数量突然增长的情况,日志服务使用了缓存加采集等待的策略。当日志产生数超过了日志服务的消费能力,先采用队列缓存(默认20000条),队列满后,对于日志采集器新上报的日志,拒绝接收并返回等待时间日志采集器收到等待时间后停止采集新日志,并不断重发已采的日志,直到服务端接收日志。该策略在一定程度上保证业务高峰期日志不丢失,并且限制入库性能后,也避免了写入日志对磁盘IO造成过大压力。

2.4 优化效果

在海豚项目环境中对优化效果进行了验证,方法先记录日志服务启动前的系统负载,再分别运行优化前和优化后的日志服务,并触发最大性能入库,记录此时的系统负载。从下图可以看出,优化后的日志服务在达到最大性能时,对系统的影响明显小于优化前。

Disk Bytes/sec(平均吞吐量) Disk Transfers/sec(平均每秒次读写次数) %idle Time(平均空闲时间)
启动日志服务前 1M/S 43 68
日志服务启动(优化之前) 16.8M/S 125 56
日志服务启动(优化之后) 2.8M/S 62 56

3 硬盘保护方案

硬盘保护方案的思路是预先设定日志数据可用磁盘的最大值,当日志服务检测到超过阈值时,采取删历史表和停止入库新日志的方式保证不占用过多硬盘。

具体流程如下:

1、日志服务启动时,从配置文件(config.properties)中读取阈值A(默认值为300G,根据一亿条日志估算);阈值A可在运管中心-系统维护-服务参数配置中配置,配置项在核心服务的WEB服务中,名称为“日志数据库最大占用空间”,单位为G

2、启动定时任务,每5分钟检查一次日志库(log_db)硬盘使用量(相关sql:select pg_database_size('log_db') as dbsize),当超过阈值时,启动日志清理,并记录操作日志,同时产生一条告警

3、清理方案

a.一次性清理现存日志中最早一天的所有日志,删除日志后记录操作日志,操作动作为“清理日志”;

b.判断是否低于阈值,若没有,则再删除一天的日志,直到仅剩当天日志;若仍无法低于阈值,停止接收日志。采集器上报日志时,向其返还错误码,采集器停止采集新日志并定时重发,直到日志服务返回正常再进行采集;触发告警,告警类型为“日志服务停止工作”,原因是“日志数据达到最大值”。

c. 若清理后低于阈值,不再继续清理,定时检查直到再次高于阈值。