如何利用Redis发布订阅模式实现分布式系统的日志收集?

浅墨吖_9123

浅墨吖_9123

2026-07-30

605人浏览

原创

redis pub/sub适合实时日志广播但不可靠,因其纯内存、无持久化、无ack、不保证顺序且消息易丢失;应作为入口网关,后接kafka/elasticsearch等持久化层,并规范json序列化与频道命名。

如何利用redis发布订阅模式实现分布式系统的日志收集?

PUB/SUB 是 Redis 实现轻量级分布式日志收集最直接的路径,但它不是万能方案——它适合实时汇聚、低延迟分发,不适合日志持久化或高可靠性场景。

为什么不能只靠 PUBLISHSUBSCRIBE 存日志?

Redis 的 PUB/SUB 是纯内存、无持久化的消息通道:一旦订阅者断连,离线期间所有消息彻底丢失;没有 ACK 机制,无法确认消费成功;也没有重试或回溯能力。这意味着:
- 日志中心进程重启后,会漏掉重启窗口内的全部日志
- 网络抖动或临时故障会导致日志“静默丢失”,且无迹可查
- 多个订阅者同时监听同一频道,每条消息会被广播给所有人(非队列语义),不适合做负载分摊

r.publish() 发送日志时必须序列化,且格式要统一

发送端不处理结构化,接收端就很难解析。常见错误是直接传 raw string 或拼接字符串,导致 JSON 解析失败或字段错位。
建议始终用 JSON 序列化,并包含必要元信息:

import json
import redis
<p>r = redis.Redis()
log_entry = {
"service": "auth-service",
"host": "node-03",
"level": "ERROR",
"timestamp": "2026-07-13T12:40:22.123Z",
"message": "Failed to validate token"
}
r.publish("logs", json.dumps(log_entry))</p>

关键点:
- 不要用 str(dict) 或 f-string 拼 JSON,必须用 json.dumps()
- 字段名保持小写、下划线风格,避免大小写混用引发解析歧义
- timestamp 必须 ISO 8601 格式(带时区),否则跨节点时间对齐困难
- 避免在消息体里塞二进制或未编码的特殊字符(如换行、控制符)

pubsub.listen() 接收端需处理连接中断与消息乱序

pubsub.listen() 返回的是一个阻塞迭代器,底层依赖 socket 连接。实际部署中常见问题包括:
- Redis 服务临时不可达 → 迭代器抛 ConnectionError,但默认不重连
- 网络延迟导致多条消息抵达顺序与发布顺序不一致(PUB/SUB 不保证顺序)
- item['type'] == 'message' 之外还有 'subscribe''unsubscribe' 类型,不判断会 crash

健壮写法示例:

Redis Skill - 高性能缓存管理
Redis Skill - 高性能缓存管理

Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。

下载
def consume_logs():
    r = redis.Redis(retry_on_timeout=True)
    pubsub = r.pubsub()
    pubsub.subscribe('logs')
<pre class="brush:php;toolbar:false;">while True:
    try:
        for item in pubsub.listen():
            if item['type'] != 'message':
                continue
            try:
                log_data = json.loads(item['data'].decode('utf-8'))
                # 写入 Kafka / ES / 文件,或转发给下游处理器
                process_log(log_data)
            except (json.JSONDecodeError, UnicodeDecodeError):
                # 跳过损坏消息,记录告警但不停止消费
                print(f"Invalid log message: {item['data'][:50]}")
    except redis.ConnectionError:
        print("Redis connection lost, reconnecting...")
        time.sleep(1)
        pubsub.close()
        pubsub = r.pubsub()
        pubsub.subscribe('logs')

真正落地时,PUB/SUB 只应作为“第一跳”,后面必须接持久化层

PUB/SUB 当作日志系统的“入口网关”,而非存储终点。典型组合:
- 发布端 → Redis PUB/SUB → 消费端(常驻进程)→ KafkaLogstash → Elasticsearch
- 或:发布端 → Redis PUB/SUB → 消费端 → r.lpush('log_queue', ...) → 后台 worker 拉取并落盘
这样既保留了 PUB/SUB 的低延迟广播优势,又通过后续环节补足了可靠性、追溯性、批量写入和水平扩展能力。

最容易被忽略的一点:频道名别硬编码成 'logs'。生产环境应按环境隔离(如 'logs-prod''logs-staging'),否则测试流量会污染线上日志流。

相关专题

更多
什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1873

5

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.07

2514

5

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

4029

19

内存数据库有哪些
内存数据库有哪些

内存数据库有Redis、Memcached、Apache Ignite、VoltDB、TimesTen、H2 Database、Aerospike、Oracle TimesTen In-Memory Database、SAP HANA和ache Cassandra。更多关于内存数据库相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.14

3555

11

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.02

6292

6

redis怎么做缓存服务器
redis怎么做缓存服务器

redis 作为缓存服务器的答案:redis 是一款开源、高性能、分布式的键值存储,可作为缓存服务器使用。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

603

6

redis怎么解决数据一致性
redis怎么解决数据一致性

redis 提供了两种一致性模型,以维护副本数据一致性:强一致性 (sync) 确保写操作仅在复制到所有从节点后才完成;最终一致性 (async) 则在主节点上写操作后认为已完成,牺牲一致性换取性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

716

6

mysql和redis怎么保证双写一致性
mysql和redis怎么保证双写一致性

确保 mysql 和 redis 双写一致性的技术包括:1、事务性更新:同时更新 mysql 和 redis,保证一致性;2、主从复制:mysql 主服务器更改同步到 redis 从服务器;3、基于事件的更新:mysql 记录更改并发送到 redis等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

5722

6

redis缓存一般存些什么数据
redis缓存一般存些什么数据

redis缓存中存储的数据类型包括:字符串、哈希、列表、集合、有序集合、位图、地理空间数据和hyperloglog。这些数据类型适用于存储各种数据,从简单信息到复杂对象和地理位置。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

1120

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
phpEnv手册
phpEnv手册

共0课时 | 0人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.5万人学习