ELK+Redis架构搭建

分布式日志分析系统:ELK 工作机制与 ELK+Redis 部署

在微服务与云原生环境中,日志分散在多台主机上,需完成收集、集中存储、检索与可视化。基于 ELK(Elasticsearch、Logstash、Kibana)及 Elastic Stack 的集中式日志平台是常见方案。

仅掌握安装命令不足以应对流量峰值或下游阻塞引发的背压。本文说明 ELK 各组件机制,阐述以 Redis 为缓冲层的 ELK+Redis 架构,并给出 CentOS 7 环境下的部署与配置要点。

理论基础与生态架构

ELK 由 Elasticsearch、Logstash、Kibana 三个组件组成,分别负责存储检索、管道处理与可视化。加入 Beats 采集组件后,整体称为 Elastic Stack;火山引擎、华为云等厂商亦提供托管服务。

Elasticsearch

Elasticsearch(ES)基于 Apache Lucene,提供分布式全文检索与分析。数据以 JSON 文档存储,无固定表结构(Schema-free),适用于非结构化或半结构化日志。

ES 支持水平扩展与近实时(Near Real-Time, NRT)搜索。底层使用倒排索引(Inverted Index):对文档分词后,建立词条到文档 ID 的映射。相比关系型数据库的 B+ 树索引,倒排索引适用于全文检索、堆栈排查及按业务标识(如 Order ID)查询。

Logstash

Logstash 是服务端数据处理管道,负责采集、清洗、字段转换与路由。数据经线程池、内存队列与 Worker 流水线处理;云厂商亦提供基于 Logstash 的托管管道。

Logstash 通过插件扩展,官方与社区提供 200 余种插件,可组合 Input、Filter、Output。处理流程分为三阶段:
Input(输入) :从文件、网络(TCP/UDP、HTTP)、消息中间件(Redis、Kafka)或 JDBC 等源接收数据。华为云等厂商提供 Redis、Elasticsearch、MySQL 等配置模板,填写连接参数即可使用。
Filter(过滤) :对原始文本进行解析,常用插件包括 Grok、Mutate、Date 等,提取 IP、日志级别、状态码等字段。
Output(输出):将处理后的事件写入目标,可同时输出至多处,如 Elasticsearch(存储与检索)、Kafka、Redis,或 Stdout、File 用于调试。

Kibana

Kibana 是 Elasticsearch 的可视化与管理界面,通过 Web 访问集群数据。支持时间序列图、地图、饼图及仪表盘等展示。除查询展示外,还提供节点监控、阈值告警、异常检测及索引生命周期管理(ILM)等功能。

Beats

早期架构常在各业务机部署 Logstash 作为采集端(Shipper)。Logstash 基于 JVM,内存与 CPU 占用较高,正则过滤会进一步增加负载。Elastic 推出基于 Go 的 Beats 系列以降低资源消耗。

Filebeat 替代原 Logstash-Forwarder,无 JVM 依赖,用于监控本地日志文件增量并发送至 Logstash、Redis 或 Kafka。常见部署形态为:边缘 Beats 采集 → 中心 Logstash 处理 → Elasticsearch 存储。

核心机制与底层原理

在高流量或下游阻塞场景下,需了解各组件在写入、刷新与落盘等环节的行为,以便调参与排障。

Elasticsearch写入原理:内存缓冲与分段机制

ES 写入并非直接落盘,数据经内存缓冲、文件系统缓存与磁盘落盘等阶段。

Lucene 将 Segment 设计为不可变(Immutable):写入磁盘后不再修改,以减少读写锁竞争。新增数据通过创建新 Segment 实现,而非重写已有 Segment。Lucene 索引包含 Commit Point 文件及多个 Segment;查询时对各 Segment 并行检索后合并结果。

写入分为内存索引缓冲(In-memory buffer)、文件系统缓存(Filesystem Cache)与磁盘落盘三层。新文档先进入内存缓冲,此时尚不可检索。Elasticsearch 定期执行 Refresh,将缓冲数据生成新 Segment 并写入文件系统缓存;进入缓存后即可被 Lucene 检索,即使尚未 fsync 到磁盘。默认 refresh_interval 为 1 秒,因此为近实时(NRT)而非严格实时。可按业务通过 refresh_interval 在检索延迟与 I/O 负载之间取舍。

Elasticsearch数据持久化:Flush与Translog事务日志

文件系统缓存中的数据在断电或崩溃时可能丢失。Flush 将 Segment 通过 fsync 写入磁盘,并更新 Commit Point。默认触发条件:距上次 Flush 满 30 分钟(index.translog.flush_threshold_period),或 Translog 达到 512MB(index.translog.flush_threshold_size);亦可按操作次数(index.translog.flush_threshold_ops)触发。

Refresh 后、Flush 完成前,ES 通过 Translog 记录未落盘操作。写入内存缓冲时同步追加 Translog,默认每 5 秒 fsync 一次。节点重启后,读取 Commit Point 并回放 Translog,恢复未 Flush 的数据。Flush 完成后截断 Translog。

核心操作机制 触发条件与系统默认频率 数据层级流向与转换 数据可搜索性 数据防断电持久性
Refresh (刷新) 默认1秒,或通过API主动请求触发 内存缓冲区 → 构建新Segment → 文件系统缓存 是(进入文件系统缓存即可被Lucene检索) 否(数据仍存在于易失性内存体系中)
Flush (落盘) 默认30分钟,或Translog体积达到512MB 文件系统缓存中的所有Segment → 强制fsync至物理磁盘 是(已持久化至磁盘)
Translog 追加 随日志写入同步追加,每5秒fsync至磁盘 操作记录日志 → 直接落入独立的Translog日志文件 否(仅用于宕机恢复,不参与搜索) 是(5秒内的极端情况存在微小丢失风险)

Logstash管道模型与持久化队列防阻塞机制

Logstash 默认使用内存队列缓存事件,容量约为 pipeline.workers(默认等于 CPU 核数)× pipeline.batch.size(默认 125)。

下游阻塞时(如 ES 写入慢、磁盘满或网络异常),Elasticsearch Output 会阻塞等待,内存队列被填满后 Input 触发背压(Backpressure),拒绝上游新数据。若此时进程被 OOM 终止或主机重启,内存队列中的事件将丢失。

持久化队列(Persistent Queue, PQ)将事件写入磁盘,降低内存队列丢失风险。

logstash.yml 中设置 queue.type: persisted 后,Input 将事件写入磁盘队列文件,再由 Filter、Output 消费。

通过 queue.max_bytes(如 8gb)限制队列容量。队列被未确认(unACKed)事件占满时,Logstash 停止接受新输入;下游恢复并 ACK 后继续接收。节点崩溃时支持至少一次(At-least-once)投递。无法解析的事件可写入死信队列(Dead Letter Queue)供后续处理。

ELK+Redis 架构原理

直连架构中,Filebeat 经 TCP 将日志发送至 Logstash,再写入 Elasticsearch。生产环境中,采集端与存储端强耦合时存在以下问题:

  • 流量冲击:日志突增时,若 ES 磁盘 IOPS 不足,背压沿链路回传至 Logstash 与 Filebeat,可能导致采集阻塞或文件描述符耗尽。
  • 维护隔离不足:ES 停机维护或 Logstash 故障时,边缘节点持续产生的日志可能无法暂存而丢失。

在采集与处理之间引入消息中间件作为缓冲,可解耦上下游。Redis 基于内存、部署相对简单,并支持 List 等数据结构,适用于中小型及部分中大型日志场景。

Redis 在链路中的缓冲作用

典型架构为:Filebeat → Redis → Logstash → Elasticsearch。

  1. 削峰:采集速率超过 ES 处理能力时,日志暂存在 Redis List 中;Logstash 按配置速率消费,减轻对 ES 的瞬时压力。
  2. 故障隔离:ES 或 Logstash 不可用时,在 Redis 内存未耗尽前,Filebeat 仍可将日志写入 Redis。Logstash 消费并写入 ES 后,对应 List 中的条目会被删除以释放内存。

数据通道模式:List、Channel、Pattern Channel

Filebeat 与 Logstash 须约定 Redis 数据模式。官方插件支持 List、Channel(Pub/Sub)及 Pattern_Channel。

List 模式:指定 Key 作为队列;Filebeat 使用 RPUSH 写入,Logstash 使用 BLPOP 消费。Logstash 离线期间,日志仍保留在 List 中,恢复后可继续处理。

Channel 模式:基于 Pub/Sub,发送方 PUBLISH,消费方 SUBSCRIBE/PSUBSCRIBE。无在线订阅者时消息不保留,存在丢失风险。

生产环境应使用 List 模式data_type: list),避免 Channel。

Redis Input 批处理与调优

不宜将 batch_count(单次从 Redis 拉取条数)设得过大。新版 Logstash Redis Input 默认在服务端用 Lua 脚本批量读取并删除。Redis 单线程执行 Lua 时为原子操作,大批量执行期间其他命令需等待。

官方测试:8 线程下,batch_count 从 125 增至 250 时,吞吐由约 89.5K 条/秒降至 72.5K 条/秒。建议保持默认 batch_count: 125。频繁执行 LLEN 等监控命令会增加竞争,影响拉取性能。

ELK+Redis 部署与配置

以下在 CentOS 7 环境下说明搭建 Filebeat → Redis → Logstash → Elasticsearch 集群的步骤。

一、 基础设施规划与系统预处理

组件关系与数据流向如下:

复制代码
    采集层          缓冲层           处理层              存储层           展示层
  ---------      ---------      -------------      --------------      ---------
  Filebeat  -->   Redis    -->   Logstash    -->   Elasticsearch -->  Kibana
  (node03)       (node01)       (node02)          (node01/02)        (node03)

  协议/命令:      RPUSH          BLPOP+Filter       HTTP :9200         HTTP :5601
                  :6379          + PQ(磁盘)         集群通信
                  key: filebeat_log_list

典型三节点拓扑如下:

节点标识 网络IP规划 部署角色划分 承载的核心服务进程
elk-node01 192.168.10.213 存储与缓存 Elasticsearch, Redis
elk-node02 192.168.10.214 存储与管道 Elasticsearch, Logstash
elk-node03 192.168.10.215 采集与可视化 Filebeat, Kibana

操作系统:CentOS Linux release 7.4.1708 (Core)。部署前在三台主机统一执行:设置主机名,关闭 Firewalld 与 SELinux(内网测试环境;生产环境应按安全策略配置防火墙规则)3。

bash 复制代码
# 修改各节点的主机名称(在三台机器上分别执行对应的名称设置)
hostnamectl set-hostname elk-node01

# 关闭防火墙并禁用开机自启
systemctl stop firewalld.service
systemctl disable firewalld.service

# 动态关闭SELinux并修改配置文件以确保持久化生效
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

二、 Redis 部署

Redis 作为缓冲层,需配置监听地址与访问认证。未部署 Cluster 时,可使用单实例或主从。修改 redis.conf 要点如下:

代码段

绑定服务器局域网内网IP或放开所有网卡监听,以允许Filebeat与Logstash跨机器连接

bind 0.0.0.0

保护模式

protected-mode yes

监听默认的标准网络端口

port 6379

访问密码(生产环境请使用强密码)

requirepass foobar2000

保存配置并启动 Redis 后,用以下命令验证连接:

bash 复制代码
redis-cli -h 192.168.10.213 -p 6379 -a foobar2000

能进入交互式命令行即表示网络连通与认证配置正确。

三、 Elasticsearch 部署

Elasticsearch 8.x 默认启用安全自动配置(Security Auto-configuration):节点间 TLS、内置账户随机密码等。内网测试环境若需简化部署,可关闭 X-Pack 安全;公网或生产环境不应关闭安全功能

在各节点编辑 $ES_PATH_CONF/elasticsearch.yml,示例配置如下:

复制代码
YAML  
\# 统一的集群标识名称,所有节点必须保持一致  
cluster.name: elk-cluster  
\# 当前节点的独立名称,区分不同实例  
node.name: node-01  
\# 业务数据块物理持久化的存储路径  
path.data: /var/lib/elasticsearch/data  
\# 节点自身运行状态日志的存储路径  
path.logs: /var/log/elasticsearch

\# 监听全网段地址,响应外部请求  
network.host: 0.0.0.0  
http.port: 9200

\# 节点发现机制的种子主机列表,指导节点去何处寻找组织  
discovery.seed\_hosts: \["192.168.10.213", "192.168.10.214"\]  
\# 声明首次引导选举时具备主节点资格的实例列表  
cluster.initial\_master\_nodes: \["node-01", "node-02"\]

\# 内网测试环境:关闭 X-Pack 安全(生产环境勿用)  
xpack.security.enabled: false  
xpack.security.autoconfiguration.enabled: false  
\# 关闭基于安全令牌机制的新节点自动化注册通道  
xpack.security.enrollment.enabled: false

配置完毕后依次拉起各节点上的Elasticsearch服务。通过浏览器或 curl 工具访问集群健康状态:

bash 复制代码
curl http://192.168.10.213:9200/_cluster/health

若返回 JSON 中 statusgreen,表示集群状态正常。

四、 Kibana 配置

因已设置 xpack.security.enabled: false,Kibana 连接 ES 时无需用户名与密码。

编辑Kibana服务所在的Node-03节点上的 kibana.yml 配置文件,将其指向Elasticsearch集群的任一活跃节点即可:

复制代码
YAML  
\# 对外提供Web页面交互访问的监听端口  
server.port: 5601  
\# 绑定主机网卡,允许外部用户通过浏览器网络访问  
server.host: "0.0.0.0"  
\# 指定Elasticsearch后端存储集群的地址列表以实现冗余查询  
elasticsearch.hosts: \["http://192.168.10.213:9200", "http://192.168.10.214:9200"\]

Kibana 启动后,通过浏览器访问 http://<节点IP>:5601 进入管理界面。

五、 Filebeat 配置

在业务服务器安装 Filebeat。filebeat.yml 定义 Input(监控的日志路径)与 Output(数据发送目标)。

应注释默认的 output.elasticsearch,改用 output.redis,并设置 data_type: list

yaml 复制代码
# ============================== Filebeat inputs ===============================
filebeat.inputs:
  - type: log
    enabled: true
    paths:
      # 业务日志路径(支持通配符)
      - /usr/local/openresty/nginx/logs/host.access.log
    fields:
      # 自定义字段,供 Logstash 条件路由
      log_source: nginx-access

# ================================== Outputs ===================================
# 注释或移除默认的 output.elasticsearch
# output.elasticsearch:
#   hosts: ["localhost:9200"]

# Redis Output
output.redis:
  hosts: ["192.168.10.213:6379"]
  password: "foobar2000"
  key: "filebeat_log_list"                    # List 键名;可用 %{[fields.list]:fallback} 动态指定
  db: 0
  data_type: "list"                           # 与 Logstash redis input 的 data_type 一致
  timeout: 5
  loadbalance: true                             # 多 hosts 时轮询

保存配置并启动 Filebeat 后,日志经 RPUSH 写入 Redis 列表 filebeat_log_list。可用以下命令检查队列长度:

bash 复制代码
redis-cli -h 192.168.10.213 -p 6379 -a foobar2000
LLEN filebeat_log_list

LLEN 返回值随日志写入递增,表示 Filebeat 到 Redis 链路正常。

六、 Logstash 配置

Logstash 配置包括 logstash.yml(含持久化队列)与 conf.d/ 下的管道文件。

1. logstash.yml 与持久化队列(PQ)

logstash.yml 中启用持久化队列(PQ),替代默认内存队列。支持扁平键或层级配置。

配置项 推荐值 说明
node.name elk-logstash-01 节点名称
pipeline.workers 4(按 CPU 核数调整) 并行工作线程数
pipeline.batch.size 125 每批处理事件数;过大可能影响 Redis 拉取
queue.type persisted 启用磁盘持久化队列
path.queue /var/lib/logstash/data/queue PQ 落盘路径
queue.max_bytes 4gb 队列容量上限;满时触发背压
queue.checkpoint.writes 1024 每 N 次写操作做一次检查点
2. 管道配置(pipeline.conf)

/etc/logstash/conf.d/(或 path.config 指定路径)创建 redis-to-es.conf,定义从 Redis List 消费(BLPOP)、Filter 处理及写入 Elasticsearch 的索引规则:

conf 复制代码
# 1. Input:从 Redis List 消费
input {
  redis {
    id          => "redis_input_01"
    host        => "192.168.10.213"
    port        => 6379
    password    => "foobar2000"
    data_type   => "list"               # 与 Filebeat output.redis.data_type 一致
    key         => "filebeat_log_list"  # 须与 Filebeat 的 key 一致
    db          => 0
    batch_count => 125                  # 过大可能延长 Lua 执行时间
    threads     => 4
  }
}

# 2. Filter:字段处理
filter {
  mutate {
    remove_field => ["@version", "beat", "host"]
  }

  # 按 fields.log_source 做条件解析(示例)
  # if [fields][log_source] == "nginx-access" {
  #   grok { match => { "message" => "%{COMBINEDAPACHELOG}" } }
  # }
}

# 3. Output:写入 Elasticsearch
output {
  elasticsearch {
    id              => "es_output_01"
    hosts           => ["http://192.168.10.213:9200", "http://192.168.10.214:9200"]
    index           => "nginx-access-log-%{+YYYY.MM.dd}"
    manage_template => true
    # ilm_enabled => false
    # 已关闭 X-Pack 安全时无需以下配置;开启安全时取消注释并填写账密
    # user     => "elastic"
    # password => "YOUR_ES_PASSWORD"
  }
}

保存管道配置后,执行语法校验:

bash 复制代码
logstash -f /path/to/redis-to-es.conf -t

当终端输出 Configuration OK 时,表示管道配置已通过语法与插件参数校验,可启动 Logstash 主服务。

Logstash 与 Redis 建立连接后,将按配置的 data_type: listkey 从列表中批量拉取日志(默认经 Lua 脚本批量 BLPOP),经 Filter 清洗后写入 Elasticsearch 指定索引;若已启用持久化队列(queue.type: persisted),在下游写入阻塞时事件会先落盘缓冲,待 Output 恢复后再继续消费。数据写入 ES 并完成 Refresh 后(默认约 1 秒),可在 Kibana 的 Discover 视图中按时间范围检索与过滤日志,用于日常运维分析与故障排查。

相关推荐
syt_biancheng8 分钟前
Redis初识
数据库·redis·缓存
是温不嗜温1 小时前
QR 准谐振反激架构:当下中小功率快充的主流选择
架构·电源管理·电源芯片·ac-dc
AI焦点1 小时前
2026年AI应用架构:如何避坑并选对API聚合中转服务?
大数据·人工智能·架构
TOPGO智能1 小时前
AI PC 端侧 AI 实战:知易智能知识管家的全栈架构与踩坑实录
人工智能·架构·高通开发
杨运交1 小时前
[032][缓存模块]基于Redis Bitmap的用户行为统计实战:签到与日活分析
数据库·redis·缓存
无关86885 小时前
Redis Bitmaps 用户签到系统设计方案
数据库·redis·缓存
小小工匠5 小时前
Redis - 如何使用 Redis 实现分布式锁
redis·性能优化·集群·并发
未若君雅裁5 小时前
日志采集与ELK:从本地日志到集中检索分析
运维·elk·jenkins
老纪6 小时前
Redis分布式锁进第九零篇
数据库·redis·分布式
JGDT_6 小时前
ERP重塑与未来趋势:SAP的实践及大一统格局(上)
大数据·人工智能·安全·架构·开源