这类问题我又碰上了一次。商品价格改成 Caffeine 本地缓存加 Redis 两层,运营改价后部分用户看到旧价格,刷新几次又变了,日志显示两台机器的本地缓存失效时间不同。

第一反应是「缓存更新与数据库更新的顺序不一致」,验证下来不成立。

真正麻烦的地方在于,几个原因的现象几乎一样。更新时先删本地再删 Redis,中间有请求把旧值写回;本地缓存没有广播失效,多实例各存一份;本地 TTL 设得太长,把不一致窗口掩盖住了。

第一件事是确认两台实例本地缓存的键与有效期

curl -s http://10.0.0.11:8080/actuator/caches && curl -s http://10.0.0.12:8080/actuator/caches

再往下改成先更新数据库再删缓存

mysql -e "update product set price=199 where id=1001;"

随后用消息广播让各实例失效本地缓存

redis-cli publish cache:invalidate 'product:1001'

给本地缓存加短 TTL 作为兜底

redis-cli ttl product:1001

怎么算真的好了,看的是同一批现象。改价后在两台机器上连续读取,返回价格在一秒内一致,重复刷新不再出现回跳。

容易忽略的是,多级缓存的失效只能靠广播或短 TTL,指望删一次就全一致不现实;价格这类强一致数据慎重放本地缓存。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189