业务中常用的 Cache Aside Pattern:
失效:先从cache中读取数据,没有得到,从数据库中读取,成功以后,放到缓存中。
命中cache: 直接返回
更新:更新数据库,删除缓存
Cache Aside 模型中,读缓存 Miss 的回填操作,和修改数据同步更新缓存,包括消息队列的异步补偿缓存,都无法满足 “Happens Before”,会存在相互覆盖的情况。
为什么需要使用消息队列异步补偿呢?
因为如果网络抖动,Cache删除失败,用户一直读取的都是旧数据,所以需要使用消息队列进行补偿进行兜底操作。
1.读缓存的miss以后,从DB中获取到数据,然后去set 缓存这个操作
2. 修改数据删除缓存数据
3. 消息队列中异步补偿缓存
这三个操作没有办法确定先后顺序的
如果当前数据库中的值是A,修改操作,将A修改为B,然后删除Cache
这个时候读操作,从数据库中读取到B进行回填操作,同时这个时候从B 改为了C,然后将缓存删除
这个时候有可能将B回填到Cache中,造成数据不一致的问题
消息队列异步补偿缓存也是这样,没有办法判断那个操作在前那个操作在后
4操作为job更新
5操作为读更新
这种交互下,4和5操作步骤都是设置缓存,导致写入的值互相覆盖,并且操作的顺序性不确定,从而导致cache存在脏缓存
写操作使用SET操作命令,覆盖写缓存,读操作,使用Add操作Redis中使用SETNX 操作回写Miss数据,保证写操作的数据不会被读操作的回写数据覆盖
参考来源:
毛剑老师 《Go进阶训练营》