如何保证数据库、缓存一致性

两阶段提交保证不了强一致性,实时一致性看业务场景,只能尽可能短时间内同步,加锁保证同一时间只能有一个线程操作,相对来说更快些来满足实时性

怎么保证数据库缓存里的数据双写一致性?在高并发下着重考虑的一个问题。

先来讲讲什么是双写,数据库在写,缓存也在写(两个存储单元)这叫双写。只要是双写,换了其他的存储单元也是一样的,比如说数据库集群,就一定会有数据一致性的问题,最常见的就是读到老数据。数据不太重要,或者是对同步的及时性要求不是那么高的其实倒无所谓,延迟更新也无关紧要。但是对于一些比较重要的数据,比如说像交易系统里的这个库存量,这时候就要特别注意数据的一致性问题。

很多小伙伴(包括我。。),一开始可能觉得,直接加锁就可以解决,只要加了锁就可以保证在更新数据库缓存的时候,只有一个线程在操作,这种就叫强一致性了。数据库、缓存肯定是同步的,也不会存在不一致的问题;但是加锁也是有缺点的,比如说在性能上面就会大打折扣,不太适合并发量比较大的一些场景。大部分场景还是需要保证性能的,那如果一定要保证最终的一致性必然会牺牲系统性能,这就是所谓的CAP理论--可用性、一致性、容错性只能同时保证两个,无法同时满足三个条件。

性能之下需要保持一致性常见的解决方案就是缓存延迟双删,先删缓存,再更新数据库,然后延迟几秒钟呢,再删一次缓存。这个延迟时间,就是读业务数据的耗时,加上几百毫秒的随机数,主要的目的就是为了确保读请求结束;写请求,可以删除,读请求可能带来的缓存脏数据。这种方案还算可以,只要休眠那一会儿,可能会有脏数据,那么一般的业务,也都能够接受,属于大并发下高性能下比较优秀的解决方案。

当然这个也不是完全没有问题,最常见的就是操作数据库或者操作缓存失败了,这种情况也是可能存在的,对于更新数据库失败,其实没有太大关系,因为此时的数据库和缓存中的还都是老数据,不存在不一致的问题,但是假设删除缓存失败,那么问题就大了,这段时间读的缓存都是老数据,我们可以设置缓存过期时间兜底,但是及时性不高,这时候呢,就必须考虑对删除操作进行重试。重试机制可以用消息队列、异步处理删除,本身也带重试机制,也可以使用这个数据库的blog,只要监测到数据库的更新,那么就执行删除缓存的操作,删除失败就记录下来等待重试。

所以总结下来,如果并发量不大啊,直接用锁保持强一致性就可以了,但是如果并发量很大,建议采用缓存延迟双删的策略来保证最终的一致性。(完)

想进一步深入了解的可以看这篇大佬的文章:技术派中的缓存一致性解决方案

ps: 如果有任何疑问,欢迎评论区给我留言


已有 0 条评论

    感谢参与互动!