一致性一般有实时一致性和最终一致性,业务如果允许最终一致性,没必要非得追求实时一致性
一般在业务里面喜欢用懒加载的方式,读的时候先读缓存,缓存没有就回源,拿到数据之后设置缓存
写的时候更新完数据库,删除旧缓存
这种方式不管是先更新缓存,还是先更新数据库,后一个如果遇到服务问题处理失败都会导致脏数据,数据不一致的情况,解决这种情况一般有两种方式
1.缓存延时双删
第一步先删除缓存,然后 更新MySQL,等过一段时间(读业务逻辑耗时+几百毫秒)再次删除缓存
先删除缓存这样缓存里面没有老数据了,在更新MySQL到最新结果,这个时候有可能在更新的前一个瞬间有一个读请求拿到了MySQL里面的老数据,如果set缓存这个时候缓存就是老数据,所以更新完MySQL之后,等 一个读请求的耗时再加上业务逻辑的耗时 让脏数据的缓存真正设置之后再去删除,这样就能保证一番操作下来不会有数据不一致的情况,不过在等待的那一段时间还是可能会出现不一致
缺点:
这种方法,更新数据还要延时,耗时比较多,不适合高并发的场景,下面还有一种方法
2.binlog同步
因为业务一般要求最终一致性就可以了,所以可以更新数据库之后删除缓存,并且保证删除缓存成功就行,如何保证缓存删除成功,可以用失败重试机制
删除失败的放到mq里面,写个程序监听这个队列,一直尝试删除,如果删除成功就确认,不然一直重试,
上面说的方法对代码有入侵,每一个更新数据的地方都要往队列里面丢数据,解决这个问题,可以监听数据库的binlog,找到更新数据的信息,丢到mq里面,专门有个地方消费mq消息去更新缓存,并且失败重试,直到成功。