Redis和Java结合的过期策略设计思路,还有一些实现细节分享
- 问答
- 2026-01-05 19:42:52
- 2
关于Redis和Java结合的过期策略设计,核心思路其实可以理解为“如何让Java程序知道Redis里的数据什么时候没了,以及数据没了之后该怎么办”,这不仅仅是设置一个TTL那么简单,而是一套需要前后端配合的完整方案。
核心设计思路:从被动清理到主动感知
最直接也最常见的思路是被动检查,这个思路很简单,就是在Java代码里,每次尝试从Redis获取数据之前,先检查一下本地是否缓存了这份数据,并且检查它是否过期,如果过期了或者根本没有,再去查询Redis,拿到数据后同时设置一个过期时间,比如set key value ex 60表示60秒后过期,这种做法实现起来最简单,对现有代码侵入小,很多早期的项目都是这么做的,但它的缺点也很明显,如果Redis里的数据因为内存不足被提前淘汰了,或者某个实例上的Java应用更新了数据,其他实例并不知道,还会继续使用过期的本地缓存,导致数据不一致。

为了解决不一致的问题,更高级的思路是主动失效,这个思路要求当数据发生变化时,主动通知所有可能缓存了该数据的Java应用实例,让它们清理掉本地缓存,Redis本身提供了一个发布订阅(Pub/Sub)功能可以用来做这件事,具体做法是,当某个Java服务实例更新或删除了Redis中的某个关键数据时,它除了操作数据库,还会向一个特定的频道(Channel)发布一条消息,内容比如是“某个key的数据已失效”,其他的Java服务实例都会订阅这个频道,一旦收到消息,就去清理自己本地缓存中对应的数据,这样就能保证各个实例的缓存能较快地保持同步,这种方式的实时性比被动检查好很多,但缺点是引入了系统的复杂性,需要维护发布订阅的链路,并且要确保消息的可靠性,比如如果某个实例当时离线了,重新上线后可能会有一段时间的数据不一致。
还有一种结合了以上两者优点的方案,也是目前比较流行的,可以称之为延迟删除结合主动触发,这个思路来自于一篇关于缓存模式的文章(通常被称为“Cache-Aside”模式的优化),具体做法是,Java应用在从Redis获取数据时,不仅获取数据本身,还会关注数据的版本号或过期时间,当Redis中的数据真正过期被删除时,我们并不完全依赖Java应用自己去发现,可以利用Redis的过期事件通知功能,我们需要在Redis配置中开启notify-keyspace-events Ex选项,开启后,当某个key过期时,Redis会发布一个事件到特定的频道,Java客户端可以监听这个频道,当收到自己关心的key过期的事件时,可以采取一些行动,比如立即去数据库加载最新数据并重新塞回Redis,或者通知其他系统,这种做法能更精确地感知Redis内部的变化,但需要注意,Redis的过期事件通知不是完全可靠的,它可能在某些情况下丢失事件,所以通常不能用于对一致性要求极高的金融场景,但对于一般互联网业务来说已经足够。

一些实现细节的分享
在实际写代码的时候,有几个细节需要特别注意。

第一,序列化问题,Java对象存到Redis前需要序列化成字节数组或字符串,常用的序列化方式有JDK自带的(体积大且慢)、JSON(可读性好但速度一般)、以及Kryo、Protobuf等(高效但需要额外依赖),选择哪种方式要根据业务对性能和可调试性的要求来定,关键是,过期时间TTL是设置在Redis的key上的,和你用哪种序列化方式无关。
第二,缓存穿透的预防,如果查询一个根本不存在的数据,每次都会绕过缓存打到数据库上,这就是缓存穿透,应对方法之一是,即使从数据库没查到,也在Redis里缓存一个空值(比如null或特殊字符串),并设置一个较短的过期时间(比如30秒),这样短时间内同样的请求就不会再访问数据库了。
第三,缓存雪崩的预防,如果大量缓存数据在同一时间点过期,会导致所有请求瞬间涌向数据库,解决方法很简单,就是给缓存的过期时间加一个随机值,比如原本统一设置60分钟过期,可以改成60分钟 + 一个0到5分钟的随机数,让缓存失效的时间点尽量均匀分布。
第四,使用成熟的Java客户端,比如Lettuce或Redisson,它们对上述这些模式都有很好的支持,Redisson内置了分布式本地缓存的功能,它可以和Redis的数据保持同步,本质上就是实现了我们上面说的主动失效思路,而且帮你封装好了,不用自己再去折腾Pub/Sub的细节,大大降低了实现的复杂度。
把Redis和Java结合用好,过期策略的设计关键是要想清楚你的业务对数据一致性的要求到底有多高,要求不高,用简单的被动检查;要求高,就要舍得花成本搭建主动失效或事件监听的机制,别忘了处理好缓存穿透和雪崩这些常见的“坑”。
本文由称怜于2026-01-05发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/75131.html
