3、日志采集与存储:日志采集工具(Filebeat、Logstash)、日志存储方案(Elasticsearch、文件系统)、日志轮转策略

日志采集与存储,是整个日志分析体系的基石。你想想看,如果连日志都收不上来、存不好,后面再牛的分析手段都是白搭。这一节,我就把这块硬骨头给大家啃透。

3.1 日志采集工具:Filebeat vs Logstash

先说采集层。市面上工具不少,但真正在生产环境里经得起考验的,我个人习惯用 Filebeat 和 Logstash 这对组合。它们俩分工明确,各司其职。

3.1.1 Filebeat:轻量级采集器

Filebeat 是 Elastic 官方出的一个轻量级采集器。说白了,它的核心任务就一个:把日志文件里的内容读出来,然后发出去。它不干别的,所以特别轻,资源占用极低。

我在项目中遇到过一台老旧的交易服务器,CPU 和内存都很紧张。当时如果上 Logstash 采集,机器直接扛不住。换成 Filebeat 后,CPU 占用率不到 5%,内存也就几十兆,完美解决。

Filebeat 的配置其实很简单。核心就三块:输入(从哪里读)、输出(发到哪里去)、以及一些处理逻辑。看个例子:

# filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/trading/*.log
  multiline:
    pattern: '^\d{4}-\d{2}-\d{2}'
    negate: true
    match: after

output.elasticsearch:
  hosts: ["localhost:9200"]
  index: "trading-logs-%{+yyyy.MM.dd}"

嗯,这里要注意 multiline 配置。交易系统的日志经常是多行的,比如一个异常堆栈会跨好几行。如果不做多行合并,Elasticsearch 里就会看到一堆碎片,根本没法分析。我刚开始用 Filebeat 时就踩过这个坑,后来才养成了必配 multiline 的习惯。

3.1.2 Logstash:强大的数据处理管道

Logstash 就不一样了。它是个重型武器,能干的事情多得多。除了采集,它还能做数据解析、过滤、转换、增强。你可以把它理解成一个数据加工厂。

为什么需要 Logstash?举个例子,交易日志里记录的金额可能是字符串 "1,234.56",但 Elasticsearch 里做聚合分析需要的是浮点数。Filebeat 干不了这个,但 Logstash 可以。

看一个典型的 Logstash 配置:

# logstash.conf
input {
  beats {
    port => 5044
  }
}

filter {
  grok {
    match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:message_body}" }
  }
  mutate {
    convert => { "amount" => "float" }
  }
  date {
    match => [ "timestamp", "ISO8601" ]
  }
}

output {
  elasticsearch {
    hosts => ["localhost:9200"]
    index => "trading-logs-%{+yyyy.MM.dd}"
  }
}

这里用到了 grok 插件来解析日志格式。我个人习惯把日志格式定义得尽量规范,这样 grok 匹配起来又快又准。如果日志格式乱七八糟,grok 规则会写得你想哭。

核心建议:Filebeat 负责采集和传输,Logstash 负责解析和加工。两者配合使用,既保证了采集层的轻量,又保证了处理层的强大。

3.2 日志存储方案:Elasticsearch vs 文件系统

日志存到哪里?这是个灵魂拷问。我见过不少团队,一开始图省事直接存文件系统,结果查询时想死的心都有。也见过一上来就上 Elasticsearch,结果集群维护成本高得吓人。

3.2.1 Elasticsearch:全文搜索与分析利器

Elasticsearch 是当前日志存储的事实标准。它为什么这么火?因为它解决了传统文件系统最大的痛点:搜索。

你想想看,如果日志存在文件里,你想查某个交易订单号的所有日志,得怎么做?要么用 grep 一行行扫,要么写脚本遍历。几百万行日志,查一次几分钟就过去了。而 Elasticsearch 基于倒排索引,毫秒级返回结果。

我在项目中遇到过线上故障,需要快速定位某个订单在哪个环节出了问题。用 Elasticsearch 的 Kibana 界面,输入订单号,一秒不到所有相关日志就出来了。如果当时用的是文件系统,估计故障都恢复了还没查完。

Elasticsearch 的索引设计也很关键。对于交易系统日志,我建议按天建索引,比如 trading-logs-2024.01.15。这样数据管理方便,过期删除也简单。

# 创建索引模板
PUT _index_template/trading-logs-template
{
  "index_patterns": ["trading-logs-*"],
  "template": {
    "settings": {
      "number_of_shards": 3,
      "number_of_replicas": 1,
      "refresh_interval": "30s"
    },
    "mappings": {
      "properties": {
        "@timestamp": { "type": "date" },
        "level": { "type": "keyword" },
        "message": { "type": "text" },
        "order_id": { "type": "keyword" },
        "amount": { "type": "float" }
      }
    }
  }
}

注意:Elasticsearch 不是银弹。如果日志量特别大(每天几百 GB 以上),集群规模会迅速膨胀,运维成本很高。这时候要考虑冷热分层存储,或者结合其他方案。

3.2.2 文件系统:简单可靠的备选方案

文件系统存储日志,虽然查询不方便,但胜在简单、可靠、成本低。对于一些非核心系统,或者日志量特别小的情况,文件系统完全够用。

我曾经维护过一个内部监控系统,每天日志量不到 100MB。这种量级上 Elasticsearch 纯属浪费。直接按日期存文件,配合 grepawk 就能搞定。

文件系统存储的关键是目录结构要规范。我建议这样组织:

/var/log/trading/
├── 2024/
│   ├── 01/
│   │   ├── trading-2024-01-15.log
│   │   ├── trading-2024-01-16.log
│   │   └── ...
│   └── 02/
└── archive/
    └── 2023/

这种结构,配合脚本做归档和清理,管理起来很顺手。

3.3 日志轮转策略

日志轮转,说白了就是不能让日志文件无限增长。否则磁盘满了,系统就挂了。这个道理大家都懂,但真正做好的不多。

3.3.1 基于大小的轮转

最常用的策略是按文件大小轮转。比如每个日志文件最大 100MB,超过就自动切分。Linux 自带的 logrotate 工具就能实现。

/var/log/trading/*.log {
    daily
    rotate 30
    size 100M
    compress
    delaycompress
    missingok
    notifempty
    create 0640 trading trading
    postrotate
        systemctl reload filebeat
    endscript
}

这里有个细节:delaycompress。它表示延迟压缩,也就是切分出来的第一个旧文件不立即压缩。为什么?因为 Filebeat 可能还在读这个文件。如果立即压缩成 .gz,Filebeat 就读不到了,会导致日志丢失。我曾经就因为这个丢过数据,后来才加上这个参数。

3.3.2 基于时间的轮转

按时间轮转也很常见,比如每天切一次。交易系统我建议按小时轮转,因为交易高峰期日志量特别大,按天轮转一个文件可能几个 GB,查询和传输都不方便。

经验之谈:轮转策略要结合采集工具一起考虑。Filebeat 有 close_inactive 参数,默认 5 分钟。如果日志轮转太快,Filebeat 可能还没来得及读完就关闭了文件句柄。我一般把轮转间隔设成 1 小时,Filebeat 的 close_inactive 设成 10 分钟,这样配合起来很顺畅。

3.3.3 保留策略

日志保留多久?这个没有标准答案,取决于业务需求和法规要求。交易系统通常要求保留 6 个月到 2 年。我建议分两层:

  • 热数据(最近 7 天):存在 Elasticsearch 里,方便快速查询
  • 温数据(7 天到 6 个月):压缩后存文件系统或对象存储
  • 冷数据(6 个月以上):归档到低成本存储,必要时再恢复

这种分层策略,既保证了查询效率,又控制了存储成本。

3.4 整体架构图

说了这么多,我画一张图把整个流程串起来。这样大家能更直观地理解日志从采集到存储的完整链路。

日志采集与存储架构图 交易应用服务器 生成日志文件 /var/log/trading/*.log Filebeat 轻量采集 多行合并、负载均衡 Logstash 数据解析与加工 Grok、Mutate、Date 存储层 Elasticsearch(热数据) 文件系统 / 对象存储(温冷数据) 日志轮转策略 基于大小:100M 切分 基于时间:每小时轮转 控制日志文件大小 Filebeat 采集 → Logstash 解析 → 分层存储(ES + 文件系统) 日志轮转策略贯穿始终,保证磁盘不爆、数据不丢

3.5 避坑指南

最后,我把自己这些年踩过的坑总结一下,大家能少走弯路就少走。

我曾经犯过的错:

  • 日志格式不统一:不同模块的日志格式五花八门,导致 grok 规则写了上百条,维护成本极高。后来我强制所有模块使用统一的 JSON 格式,解析效率提升 10 倍。
  • 忽略磁盘监控:有一次日志量突然暴增,磁盘写满,导致交易系统直接挂掉。从那以后,我必配磁盘告警,阈值设在 80%。
  • Filebeat 版本不匹配:Filebeat 和 Elasticsearch 的版本要匹配,否则可能出现兼容性问题。我建议保持大版本一致。

好了,日志采集与存储这块就讲到这里。记住一句话:采集要轻、存储要稳、轮转要勤。把这三点做到位,你的日志体系就成功了一大半。