3. Redis实时数据平台总体架构设计

实时数据平台的核心矛盾在于:数据产生速度远快于人工处理速度,而业务又要求毫秒级响应。Redis 在这个矛盾中扮演的角色,不是简单的缓存,而是实时数据面的中枢——它承接接入层写入、支撑计算层状态、承载存储层热数据、并通过服务层对外输出。本节从五层架构出发,明确每层的职责边界、Redis 的定位,以及一条数据从进入到被消费的完整路径。

五层架构的职责划分

接入层负责把外部数据源统一收口。典型来源包括业务应用的埋点上报、MySQL binlog 变更、IoT 设备 MQTT 消息、以及第三方 API 回调。接入层不做过重逻辑,只做协议适配、格式校验和初步限流,然后把标准化后的事件写入 Redis Stream 或 Kafka。选择 Redis Stream 的场景通常是:数据量中等、要求极低延迟、且下游消费者数量有限;选择 Kafka 的场景则是:需要长期留存、多消费组独立消费、或吞吐量超过单实例 Redis 的承受范围。

计算层是实时逻辑的发生地。它从接入层读取事件,做窗口聚合、规则匹配、状态维护,再把结果写回 Redis 或下游存储。Redis 在计算层的价值体现在两个数据结构上:Hash 用于维护实体最新状态(如设备最新温度、订单最新状态),Sorted Set 用于时间窗口内的排序与范围查询(如最近 5 分钟交易额 TopN)。计算层通常由 Flink 或自研消费者进程实现,Redis 作为其状态后端或结果暂存区。

存储层解决"热数据放哪里、冷数据放哪里"的问题。Redis 承担热数据层,保存最近数分钟到数小时的高频访问数据;历史数据落到 ClickHouse、HBase 或对象存储。两者之间通过 TTL 和异步归档衔接:Redis 中的 Key 设置过期时间,过期前由归档任务批量写入冷存储。这样既保证了查询性能,又控制了内存成本。

服务层是业务系统直接调用的接口面。它不直接暴露 Redis 命令,而是封装成 gRPC 或 HTTP 接口,内部完成 Key 路由、批量聚合、降级兜底。服务层需要处理的关键问题是:当 Redis 不可用时,是返回空值、返回降级数据、还是直接报错。这取决于业务对一致性的容忍度。

治理层贯穿所有层,负责监控、告警、配置管理和权限控制。它不参与数据流,但决定了平台能否稳定运行。治理层需要采集的指标包括:Redis 内存使用率、命中率、慢查询数量、Stream 积压长度、以及各层之间的端到端延迟。

治理层 · 监控告警 / 配置管理 / 权限控制 / 链路追踪 贯穿五层,采集内存、命中率、慢查询、Stream积压、端到端延迟 接入层 · 协议适配 / 格式校验 / 初步限流 业务埋点上报 MySQL binlog IoT MQTT 消息 第三方 API 回调 Redis Stream 事件流 计算层 · 窗口聚合 / 规则匹配 / 状态维护 Flink 消费进程 窗口聚合 · 规则引擎 自研消费者 状态更新 · 结果写回 Redis Hash 实体最新状态 Redis Sorted Set 时间窗口排序 结果写入 存储层 · 热数据 / 冷数据分层 Redis 热数据层 最近数分钟~数小时 · TTL 控制 ClickHouse / HBase 历史数据 · 异步归档 对象存储 冷备 · 合规留存 查询读取 服务层 · gRPC / HTTP 接口封装 Key 路由 · 批量聚合 降级兜底 · 限流熔断 结果缓存 · 协议转换 业务系统调用入口 数据流方向 ↓

Redis 在架构中的定位

从上面的架构图可以看出,Redis 不是某一层的专属组件,而是横跨计算层与存储层的实时数据面。具体来说,它承担四个角色:

  • 接入缓冲:当接入层使用 Redis Stream 时,Redis 充当事件队列,消费者通过 XREADGROUP 按消费组读取,支持 ACK 确认和积压监控。
  • 计算状态:计算层用 Hash 维护实体最新状态,用 Sorted Set 维护时间窗口排序。例如设备状态用 HSET device:status:{id} temp 36.5 ts 1710000000,窗口排名用 ZADD window:5min:amount {amount} {order_id}。
  • 热数据存储:服务层查询时优先读 Redis,未命中再回源冷存储。热数据的 TTL 根据业务访问模式设定,通常为 5 分钟到 2 小时。
  • 服务层缓存:服务层对高频查询结果做二级缓存,减少对计算层和存储层的重复压力。

一条数据的完整路径

以"电商订单实时风控"为例,一条订单事件从产生到被风控规则消费,路径如下:

  1. 订单服务产生事件,通过 HTTP 上报到接入层,接入层校验字段完整性后写入 Redis Stream stream:order:events。
  2. Flink 消费进程通过消费组 risk-engine 读取事件,解析出用户 ID、订单金额、收货地址等字段。
  3. Flink 查询 Redis Hash user:profile:{uid} 获取用户历史行为特征,同时用 Sorted Set user:orders:1h:{uid} 统计近 1 小时订单数和总金额。
  4. 规则引擎判断是否触发风控阈值(如 1 小时内下单超过 10 笔且总金额超过 5000 元),若触发则写入告警 Stream stream:risk:alerts。
  5. 服务层通过 gRPC 接口对外提供风控查询,内部先查 Redis 缓存,未命中再查 ClickHouse 历史记录。

这条路径中,Redis 出现在第 1、3、5 步,分别承担缓冲、状态查询和缓存职责。端到端延迟的瓶颈通常在第 3 步的多次 Redis 往返,优化手段包括:用 Pipeline 合并命令、用 Lua 脚本保证原子性、以及把部分聚合逻辑下沉到 Redis 的 Sorted Set 范围查询中。

关键设计决策与参数示例

架构落地时需要明确几个关键参数。以下是一组教学示例参数,实际值需根据压测结果调整:

决策项 示例值 判断依据
Stream 最大长度 100000 条 按峰值写入速率 × 消费者最大处理延迟估算
热数据 TTL 30 分钟 业务查询 95% 集中在最近 30 分钟
Hash 字段数上限 50 个 避免单 Key 过大导致网络往返和内存碎片
Sorted Set 窗口大小 5 分钟 / 1 小时 / 24 小时 对应风控、运营、报表三类查询场景
服务层降级策略 返回最近一次缓存值 风控场景可容忍秒级延迟,不可返回空
实践提示:Redis 在实时架构中的定位不是"万能存储",而是"实时数据面"。判断一个数据是否适合放 Redis,问三个问题:访问频率是否高?是否要求毫秒级响应?是否可容忍丢失或过期?三个都是"是",才放入 Redis 热数据层。
常见误区:把 Redis 当唯一存储使用,不设 TTL、不做冷备归档。一旦内存打满或实例故障,历史数据无法恢复。正确做法是:Redis 只保存热数据,冷数据必须异步落到持久化存储,且归档任务要有幂等和重试机制。

五层架构的最终目标是让数据在"接入—计算—存储—服务"之间形成闭环,而治理层保证这个闭环可观测、可控制。Redis 的定位贯穿其中,但每一层的使用方式不同:接入层用它做队列,计算层用它做状态,存储层用它做热数据,服务层用它做缓存。明确这个分层定位,后续的容量规划、故障排查和性能优化才有清晰的边界。