延迟任务

用zset的score存储过期时间,

循环去扫描,到期了就去执行业务逻辑

成熟方案:使用RocketMQ的延时消息

大key

阻塞请求(最严重):Redis 是单线程的。如果对一个包含 100 万个元素的 Set 执行 SMEMBERSDEL,会导致 Redis 主线程卡顿,期间无法处理其他任何请求。

网络拥塞:大 Key 传输会占用大量带宽,可能导致网卡流量打满,影响其他业务。

内存不均(针对 Cluster):在 Redis Cluster 中,一个巨大的 Key 无法被拆分到多个节点【==Cluster是均衡key的数量,但是key较大,那这个Cluster分片上的内存就会较大==】,导致某个分片的内存远大于其他节点,形成瓶颈。

过期/删除困难:大 Key 的被动过期或主动删除(DEL)会非常慢。虽然 Redis 4.0+ 支持 UNLINK(异步删除),但逻辑上的处理依然复杂。

解决:

  1. 分key

    1
    2
    3
    4
    # 分key之后,分片可能不在一个集群分片上,可以使用hashtag{}来指定计算hash的部分,这样前面相同就会在一个分片上了,但是一般不这样做,key分片就是为了分散它
    {user:1001}:part0
    {user:1001}:part1
    {user:1001}:part2
  2. unLink异步删除大key

热key

多级缓存:Caffeine创建一个本地缓存对象,先查它,没有就查redis,并存入本地缓存;还没有就查数据库,并存入本地缓存和redis;数据变更时redis直接删除,通过消息队列订阅机制让各个服务器删除本地缓存

预热

SpringBoot启动时查出热key先存入Redis里

image-20260521170419514

注意:

  1. 如果预热的数据量很大(上万条),直接在启动线程跑会拖慢应用启动速度,结合 @Async异步执行预热逻辑,不阻塞主线程
  2. 预热的数据如果在预热期间被修改了,可能会短暂不一致【做好一致性,修改了:业务代码就删缓存或者Canal监听BinLog有修改就删】