3. 日志存储与管理:从架构到实战

日志存储这件事,说简单也简单,说复杂真能让人头疼。我见过不少团队,前期图省事把日志全堆在一台服务器上,结果半年后磁盘爆了,查个日志比登天还难。今天咱们就聊聊,怎么把日志存得明白、管得省心。

3.1 集中式 vs 分布式:选哪个?

先问个问题:你手上有多少台机器?10台以内,还是100台以上?这个答案基本决定了你的选择。

集中式存储,说白了就是把所有日志都发到一台中央服务器上。我早期做项目时就这么干,一台高配服务器,装个Rsyslog,搞定。优点是简单、好维护,查日志直接上那台机器就行。缺点嘛……你想想看,如果机器挂了,所有日志都丢了。而且单机性能有限,每天几个GB的日志量还能扛,到了TB级别就卡得不行。

分布式存储,则是把日志分散到多台机器上。比如用Elasticsearch集群,数据自动分片,查询也快。我在一个金融客户那里见过,每天产生几十TB的日志,用3个节点的ES集群扛着,查询响应还在秒级。但代价是运维复杂,你得懂集群调优、分片策略、节点故障恢复这些。

我的建议:

  • 日志量 < 50GB/天,机器 < 20台 → 集中式够用
  • 日志量 > 500GB/天,机器 > 100台 → 必须分布式
  • 中间地带 → 看团队能力,别硬上分布式

3.2 日志轮转策略:别让磁盘爆了

日志如果不轮转,后果很严重。我曾经接手过一个系统,发现某台机器的/var/log目录占了200GB,一查是某个应用的debug日志,从去年写到今年,从来没轮转过。嗯,这里要注意:日志轮转不是可选项,是必选项。

常见的轮转策略有几种:

策略 触发条件 适用场景
按大小轮转 文件达到100MB 日志量稳定的场景
按时间轮转 每天/每小时切一次 需要按时间归档的场景
混合策略 大小或时间,谁先到谁触发 最推荐,兼顾两者

我个人习惯用logrotate,Linux自带的工具,配置起来很简单。举个例子:

/var/log/myapp/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 0640 root root
    postrotate
        systemctl reload myapp > /dev/null 2>&1 || true
    endscript
}

这段配置的意思是:每天轮转一次,保留30天的日志,轮转后压缩。注意那个postrotate,很多应用在日志被切走后需要重新打开文件句柄,不然日志就写丢了。我踩过这个坑,所以现在都会加上。

避坑指南:我曾经遇到过logrotate配置了但没生效的情况,排查半天发现是cron没启动。记得检查/etc/cron.daily/logrotate是否在运行。

3.3 日志压缩与归档:省钱又省心

日志压缩,说白了就是用CPU换磁盘空间。gzip压缩率通常在80%以上,一个100MB的文本日志,压缩完不到20MB。代价是查询时需要解压,但如果你用ELK这类工具,压缩是透明的,用户感觉不到。

归档策略我一般这么定:

  • 热数据(最近7天):不压缩,保持快速查询
  • 温数据(7-30天):压缩存储,保留原始格式
  • 冷数据(30天以上):归档到廉价存储,比如对象存储或磁带

我在一个电商项目中,每天产生约1TB的访问日志。用这个策略,热数据只占7TB,温数据压缩后不到5TB,冷数据直接扔到阿里云OSS上,成本降了80%。

3.4 ELK Stack 入门:三剑客

ELK是Elasticsearch、Logstash、Kibana的合称。说白了,就是一套帮你收日志、存日志、看日志的工具链。

Elasticsearch:存储和搜索引擎。数据以JSON格式存入,支持全文检索和聚合分析。我习惯把它想象成一个超级大的Excel,但查询速度快了100倍。

Logstash:数据采集和处理管道。它可以从各种源头(文件、TCP、Kafka)读取日志,然后做过滤、转换、格式化,最后输出到ES。举个例子:

input {
    file {
        path => "/var/log/myapp/*.log"
        start_position => "beginning"
    }
}

filter {
    grok {
        match => { "message" => "%{COMBINEDAPACHELOG}" }
    }
    date {
        match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
    }
}

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

这段配置从日志文件中读取数据,用grok解析成结构化字段,然后按天存入ES。注意那个start_position,我第一次用的时候没设,结果只读到了新产生的日志,历史数据全丢了。

Kibana:可视化界面。你可以在上面画图表、建仪表盘、做告警。我最常用的功能是"Discover",直接搜索关键词,几秒内就能定位到问题日志。

注意:ELK Stack的版本兼容性是个坑。比如Elasticsearch 7.x和Logstash 7.x是配套的,但和6.x就不兼容。我建议统一使用最新稳定版,或者至少大版本一致。

3.5 实战建议:从小做起

如果你刚开始接触日志管理,别一上来就搞分布式集群。我的建议是:

  1. 先在一台机器上搭个单节点的ELK,跑通流程
  2. 把最重要的系统日志(比如Nginx、MySQL、应用日志)接入
  3. 用Kibana建几个简单的仪表盘,比如"最近24小时错误数"、"请求量趋势"
  4. 等熟悉了,再考虑扩容到多节点

我记得第一次给客户演示ELK时,现场查出了一个隐藏了三个月的性能瓶颈。客户当场就说:"这个工具值了。" 嗯,这就是日志管理的魅力——数据不会骗人,关键是你得会用工具把它挖出来。