本文是大数据系列第 38 篇,介绍 Redis 的定位与核心能力,重点讲解生产中最常用的三种缓存读写模式。

完整图文版(含截图):CSDN 原文 | 掘金

Redis 简介

Redis(Remote Dictionary Server)是用 C 语言开发的开源高性能键值对存储系统。它将数据存储在内存中,读写速度可达数十万 QPS,同时通过 RDB 和 AOF 机制保障数据持久化。

主要特点:

  • 内存存储:极快的读写速度,典型读写延迟在微秒级
  • 持久化:RDB(快照)和 AOF(追加日志)双保险
  • 丰富的数据结构:String、Hash、List、Set、Sorted Set
  • 高可用性:主从复制 + 哨兵模式,支持自动故障转移
  • 事务支持MULTI/EXEC 命令块原子执行

五大核心数据类型

类型典型使用场景
String(字符串)缓存简单数据、计数器、分布式锁
Hash(散列)存储对象/用户信息、购物车数据
List(列表)消息队列、最新动态、粉丝列表
Set(集合)标签系统、共同好友、去重统计
Sorted Set(有序集合)排行榜、带权重队列、范围查询

常见使用场景

  • 热点数据缓存:将高频 DB 查询结果缓存到 Redis,可将数据库 QPS 降低 50%–90%
  • Session 分离:集群环境下所有 Tomcat 实例共享 Redis Session,避免传统 Session 复制的性能问题
  • 分布式锁SET key value NX EX ttl 实现轻量级分布式互斥
  • 任务队列:秒杀、抢红包等高并发写场景削峰填谷
  • 排行榜:Sorted Set 天然支持按分值排序
  • 签到统计:Bitmap 高效存储布尔型时序数据

缓存读写模式

旁路缓存模式(Cache Aside Pattern)

最常用的模式,应用程序直接管理缓存与数据库的一致性。

读操作流程:

  1. 查询 Redis 缓存
  2. 缓存命中 → 直接返回
  3. 缓存未命中 → 查询数据库
  4. 将查询结果写入 Redis(设置合理的 TTL)
  5. 返回数据

写操作流程:

  1. 更新数据库
  2. 删除(而非更新)对应的缓存 key

为什么写操作要删除而不是更新缓存?更新操作存在并发写时的竞态条件(两个线程先后写库后先后写缓存,顺序可能错乱),删除操作是幂等的,下次读时重建缓存更安全。

潜在问题:

  • 缓存穿透:频繁查询不存在的 key,可用布隆过滤器或缓存空值解决
  • 缓存击穿:热点 key 过期瞬间大量请求打到数据库,可用互斥锁或逻辑过期解决
  • 数据不一致窗口:数据库更新后到缓存删除成功前的短暂不一致

读写穿透模式(Read/Write Through Pattern)

应用程序只与缓存交互,由缓存层负责与数据库同步。缓存未命中时,缓存自动从数据库加载数据;写入时,缓存同步写入数据库后再返回成功。

适用场景:需要缓存层屏蔽存储细节,逻辑简单但依赖缓存框架支持(如 Spring Cache)。

异步写回模式(Write Behind / Write Back Pattern)

应用程序只更新缓存,缓存将数据异步批量刷写到数据库,类似 CPU L1/L2 缓存机制。

优势:写性能极高,适合写多读少场景。

缺点

  • 缓存宕机可能丢失未持久化的数据
  • 数据库中的数据可能短暂滞后,不适合强一致性场景

模式对比

模式一致性复杂度适用场景
Cache Aside最终一致通用场景,读多写少
Read/Write Through强一致需要透明缓存的业务
Write Behind弱一致极高写吞吐,可接受数据丢失