合理设计日志存储结构
日志量一大,查起来就慢,根本原因往往出在存储设计上。很多团队一开始图省事,把所有日志扔进一个大表,时间一长,几亿条记录堆在一起,哪怕加了索引也扛不住。更好的做法是按时间分表,比如每天或每周一个表,查询时先定位时间段,直接缩小数据范围。
如果用的是Elasticsearch这类搜索引擎,可以配合索引滚动策略,比如用logs-2024-04-01这样的命名方式,再通过索引别名统一查询入口,既方便管理又能提升性能。
只采集必要的日志字段
不是所有信息都需要记录。有些服务默认打全量请求体,包含大量冗余数据,不仅浪费磁盘,还拖慢查询速度。建议在日志输出前做一次筛选,只保留关键字段,比如请求ID、用户ID、接口路径、响应状态码和耗时。
举个例子,原本一条日志可能有2KB,去掉无用字段后压缩到300字节,同样的查询条件,I/O压力直接下降80%以上。
使用分区和索引策略
数据库或日志系统中的分区机制能显著提升查询效率。以MySQL为例,按日期对日志表进行 RANGE 分区,查询某天的数据时,数据库只会扫描对应分区,而不是全表遍历。
CREATE TABLE logs (
id BIGINT,
log_time DATETIME,
level VARCHAR(10),
message TEXT
)
PARTITION BY RANGE (YEAR(log_time) * 100 + MONTH(log_time)) (
PARTITION p202401 VALUES LESS THAN (202402),
PARTITION p202402 VALUES LESS THAN (202403),
PARTITION p202403 VALUES LESS THAN (202404)
);同时,对高频查询字段建立复合索引,比如(log_time, level),避免在查询错误日志时全表扫描。
避免在高峰时段执行复杂查询
开发同事半夜收到告警,急着去查日志,顺手写了个模糊匹配全表搜索,结果数据库CPU瞬间飙到95%,影响线上服务。这种情况并不少见。大查询尽量避开业务高峰期,或者把原始日志同步一份到独立的分析集群,用副本做聚合和挖掘。
像Kibana里设置慢查询阈值,超过2秒就告警提醒,也能帮助团队养成良好习惯。
预聚合常用指标
并不是每次都要看原始日志。多数时候我们关心的是“今天5xx有多少”、“哪个接口最慢”。把这些高频统计做成预聚合任务,每5分钟跑一次,结果存入轻量表或Redis,前端直接读聚合结果,响应从十几秒变成几十毫秒。
比如用Logstash或Flink消费日志流,提取关键指标:
| source | status | duration |
|--------|--------|----------|
| api-gateway | 500 | 1200 |
| order-service | 200 | 80 |然后按服务维度统计错误率和P95耗时,展示在监控面板上,既减轻查询压力,又提升排查效率。
善用工具链的过滤能力
很多开发者习惯先把大量日志拉到本地再慢慢筛,其实现代日志平台都支持链路级过滤。比如在查询语句里加上service: user-center AND level: error,系统会在检索阶段就完成过滤,传输的数据量大幅减少。
再比如用Grep、JQ这类命令行工具,在日志服务器上直接处理,避免把整个文件下载下来再打开记事本搜索。