什么是数据版本号?
DB 中的数据,插入时版本号为0,每更新一次,版本号加1。
具体见 数据版本号。
什么情况下缓存不是最新数据?
举个例子,有两个线程尝试把同一条数据写入缓存,假设都是先更新DB,再更新缓存,那么当出现下面的情况时,缓存不是最新数据:
- 线程1在DB中修改数据
- 线程2在DB中修改数据
- 线程2更新缓存
- 线程1更新缓存
如何保证?
缓存支持数据的版本号,在更新缓存时,新数据的版本号必须大于缓存中已有数据的版本号。
redis 该怎么具体实践?
DB 里要有数据版本号。
redis 本身没有数据版本号的概念,我们可以用将数据版本号存进去。通过 Lua 保证原子性。
例如,我们要存用户 xiaoming 的身高信息,缓存生存时间为 10 分钟。
方式1:lua + 两个 key
一个key是 xiaoming:height
,一个 key是xiaoming:height:version
。xiaoming:height:version
的缓存生存实践可以大一些,例如 11 分钟。
思路是:
- 若
xiaoming:height
不存在,则直接设置xiaoming:height
、xiaoming:height:version
,流程结束。 - 若
xiaoming:height
存在,则查询xiaoming:height:version
,若缓存版本号大于等于要新设置的版本号,则什么都不做,流程结束。 - 若缓存版本号小于要新设置的版本号,则设置
xiaoming:height
、xiaoming:height:version
。
方式2:lua + 一个 key + 从value 中解析版本号和数据
和方式1类似,不过版本号和数据都存在一个key里面。
方式3:lua + hash 类型
和方式2类似,用 hash 保证数据结构化,hash 中用 data key 存数据,用 version key 存版本号。