实时系统无法容忍缓慢的数据库查询。无论工作负载是实时仪表盘、多人游戏、交易平台还是遥测数据管道,用户都期望在毫秒级内获得响应。Redis 和内存缓存(in-memory caching)是满足这些期望的常用工具,但它们并不能替代周密的数据库设计。
本文介绍如何将 Redis、内存缓存与持久化数据库结合起来,以支撑低延迟的实时工作负载。
Redis:将热数据放入内存
Redis 将频繁访问的数据保存在 RAM 中,并以微秒级响应简单操作。它非常适用于:
- 会话存储与速率限制器
- 排行榜、计数器与实时排名
- 发布/订阅(pub/sub)消息与任务队列
- 带有明确过期时间的查询结果缓存
Redis 之所以快,是因为它将所有数据保存在内存中。这也意味着,对于任何无法重建的数据,它都不能充当主数据存储。请根据您的应用能够容忍的数据丢失量来规划持久化与复制策略。
面向低延迟的数据库设计
即使前面挡着缓存,数据库本身也必须足够快,才能应对缓存未命中(cache miss)以及缓存无法吸收的写入。关键技术包括:
- 为实时查询所用的列建立索引
- 通过分区或分片(sharding)分散负载
- 将热数据放在 NVMe 等高速存储上
- 调优连接池与查询计划
- 使用只读副本承载分析与报表类工作负载
即使每个查询结果都被缓存,索引不当的数据库仍然会很慢,因为写入和缓存失效最终仍会打到持久化层。
实时数据栈的分层
| 层级 | 作用 | 示例 |
|---|---|---|
| 内存缓存 | 亚毫秒级读写 | Redis、Valkey |
| 业务数据库 | 事务性持久化 | PostgreSQL、MySQL |
| 流处理器 | 事件摄入与转换 | Kafka、Pulsar |
| 分析型存储 | 历史查询与仪表盘 | ClickHouse、TimescaleDB |
基础设施容量规划
实时基础设施需要的是可预测的资源,而不仅仅是平均意义上的富余。Redis 对内存限制尤其敏感:一旦内存耗尽,它就必须驱逐键、拒绝写入或使用交换分区(swap),而这些都会摧毁延迟表现。
- 按峰值工作集外加增长空间来规划 Redis 内存
- 配备足够快的 CPU 核心,以处理大量并发连接
- 在应用与缓存之间使用低延迟网络
- 为故障转移部署 Redis 复制,但要将复制延迟(replication lag)考虑在内
- 为数据库配置足够的 IOPS,以吸收缓存未命中带来的压力
目标是让工作集保持热度,并让持久化层足够快,使缓存未命中不会级联演变为服务中断。