Redis 缓存入门:常用数据结构与典型应用场景
为什么需要缓存
很多系统变慢,并不是数据库本身不够快,而是同样的查询被反复执行:商品详情、用户信息、排行榜、配置信息,这些数据读得多、改得少,每次都去查库既浪费连接,也拉高了响应时间。缓存的思路很直接:把热点数据放在离应用更近、访问更快的地方,读请求先查缓存,命中就直接返回,只有未命中时才回源查库并回填。
Redis 是目前最常用的内存缓存之一。它把数据放在内存里,读写延迟很低,还支持丰富的数据结构,不只是一个简单的键值对仓库。理解它的常用结构,才能在不同场景里选对工具,而不是把所有问题都塞进字符串里。
String:最简单的万能结构
String 是最基础的结构,一个键对应一个值,值可以是文本、数字,也可以是序列化的对象。常见用法包括缓存单个对象、计数、分布式锁的辅助值,以及用过期时间控制短期数据。
例如:
SET user:1001 "{\"name\":\"zhangsan\",\"level\":3}" EX 3600
GET user:1001
INCR page:view:home
使用 String 时要注意两点:一是值不宜过大,过大的对象会占用内存、拖慢序列化;二是需要过期时间时一定要设置,否则缓存会长期堆积,变成事实上的永久存储。
Hash:把对象拆成字段
当一个对象有多个字段,而且经常只改其中一两个字段时,Hash 更合适。它把一个键映射为多个字段,读改都可以只针对单个字段,不用整存整取。
HSET user:1001 name zhangsan level 3 city shenzhen
HGET user:1001 level
HGETALL user:1001
用户信息、商品属性、配置分组都适合用 Hash。它的好处是节省往返次数,也减少了因为改一个字段而重写整个对象的开销。
List:有序的队列与时间线
List 是按插入顺序排列的元素集合,支持从两端 push 和 pop,天然适合做队列和时间线。消息队列可以用 LPUSH 加 BRPOP 实现简单的生产消费;最新动态可以用 LPUSH 写入,再用 LRANGE 取前若干条;任务待处理列表也可以用它暂存。
需要注意的是,List 适合顺序消费和有限长度的场景,不适合频繁按下标随机访问或按条件查找,大量元素的中部操作成本较高,长度也应当控制,避免无限增长。
Set:去重与关系判断
Set 是无序、不重复的集合,适合做去重和关系运算。签到用户集合、点赞用户集合、标签集合都可以用它表示。SADD 加入,SISMEMBER 判断是否存在,SINTER 求交集,SUNION 求并集,这些操作在内存中完成,速度很快。
例如,共同关注、共同标签、黑名单判断,都可以用集合运算直接得出结果,而不需要把数据拉回应用层再逐条比较。
ZSet:带分数的有序集合
ZSet 在 Set 的基础上给每个成员加了一个分数,按分数排序,适合排行榜、延迟任务和按优先级排序的场景。ZADD 写入带分数的成员,ZREVRANGE 取分数最高的前若干名,ZRANGEBYSCORE 可以按分数区间查询,ZSCORE 可以查单个成员的分数。
积分榜、热度榜、按时间排序的待办任务,都可以用 ZSet 实现。它的排序由 Redis 维护,应用层不需要再做全量排序,分页取榜单也很方便。
缓存策略:先读缓存,再回源
最常见的读策略是 Cache Aside:先查缓存,命中返回;未命中查数据库,查到后写回缓存并设置过期时间。写策略则要根据一致性要求选择:可以先更新数据库再删除缓存,让下一次读重新回填;也可以先删缓存再更新数据库,但要处理并发读导致的旧值回填。
无论选哪种,都要接受一个基本事实:缓存与数据库之间很难做到强一致。多数业务场景接受短暂不一致,关键是把不一致的窗口控制在可接受范围内,并且对金额、库存这类敏感数据做额外的校验和兜底。
三个常见坑:穿透、击穿与雪崩
缓存穿透是指请求的数据根本不存在,缓存查不到,数据库也查不到,请求每次都打到数据库。缓解办法包括对空结果也做短时间缓存、做参数校验,以及在入口层拦截明显非法请求。
缓存击穿是指某个热点键过期的一瞬间,大量并发请求同时回源。缓解办法包括给热点键加逻辑过期、互斥锁回源,或者提前预热,让过期不发生在高峰期。
缓存雪崩是指大量键在同一时间过期,或者缓存整体不可用,导致请求集中涌向数据库。缓解办法包括过期时间加随机抖动、多级缓存、限流降级,以及做好缓存服务的容量与监控。
什么时候不适合用缓存
缓存不是万能药。写多读少的数据、强一致要求很高的数据、数据量巨大但命中率很低的数据,都不适合一味缓存。缓存还会带来运维成本:内存容量、过期策略、持久化、主从与集群、监控告警,都需要有人维护。
上线缓存前,先回答三个问题:这份数据的读频率有多高?不一致能容忍多久?缓存挂了业务还能不能降级运行?回答清楚这三个问题,再选结构、定过期时间、做兜底,缓存才能真正提速而不是添乱。
上手检查清单
一是按场景选结构:单个对象用 String,对象字段用 Hash,队列用 List,去重用 Set,排行用 ZSet。二是所有缓存键都要有过期时间,并给批量过期加随机抖动。三是键名要有命名规范,例如业务前缀加冒号加标识,便于排查和批量管理。四是关键路径要有降级:缓存不可用时直接查库或返回默认值,不要让缓存故障变成全站故障。五是上线后看命中率、内存占用和慢查询,定期清理不再使用的键。
把这份清单做成习惯,Redis 就不再只是一个装数据的盒子,而是一套可预期、可维护的缓存层。
- 点赞
- 收藏
- 关注作者
评论(0)