如何保证缓存与数据库的双写一致性?

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

1. 对删除缓存进行重试,数据的一致性要求越高,我越是重试得快。

2. 定期全量更新,简单地说,就是我定期把缓存全部清掉,然后再全量加载。

3. 对同一数据的读取/写入请求串行,保证同一数据的请求消息,都会路由到同一个服务上。一般来说,如果允许缓存可以稍微的跟数据库偶尔有不一致的情况,也就是说如果你的系统不是严格要求 “缓存+数据库” 必须保持一致性的话,最好不要做这个方案,即:读请求和写请求串行化,串到一个内存队列里去。串行化可以保证一定不会出现不一致的情况,但是它也会导致系统的吞吐量大幅度降低,用比正常情况下多几倍的机器去支撑线上的一个请求。

4. 给所有的缓存一个失效期。

面试题

如何保证缓存与数据库的双写一致性?

面试官心理分析

你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?

面试题剖析

A:如果允许缓存可以稍微的跟数据库偶尔有不一致的情况,也就是说如果你的系统不是严格要求 “缓存+数据库”

策略:1.删除缓存,2.更新数据,3.删除缓存

B:必须保持一致性的话,最好不要做这个方案,即:读请求和写请求串行化,串到一个内存队列里去。

高并发下一致性问题

场景:当流量上亿,问题会出现

问题:数据发生了变更,先删除了缓存,然后要去修改数据库,此时还没修改。一个请求过来,去读缓存,发现缓存空了,去查询数据库,查到了修改前的旧数据,放到了缓存中。随后数据变更的程序完成了数据库的修改。完了,数据库和缓存中的数据不一样了…

策略:更新数据的时候,根据数据的唯一标识,将操作路由之后,发送到一个 jvm 内部队列中。读取数据的时候,如果发现数据不在缓存中,那么将重新读取数据+更新缓存的操作,根据唯一标识路由之后,也发送同一个 jvm 内部队列中。

等于将并行任务,做成了串行任务。

问题1:更新并发量过大,请求阻塞

要加机器,将更新(包含添加)操作,分布到不同的机器

问题2:读请求过大

当读请求过大,一样的加机器,测试单机压力,保证正常写入不影响机器读性能

问题3:多服务器部署

比如说,对同一个商品的读写请求,全部路由到同一台机器上。可以自己去做服务间的按照某个请求参数的 hash 路由,也可以用 Nginx 的 hash 路由功能等等。

问题4:热点商品的路由问题,导致请求的倾斜

的确存在单机某个商品读和写的量很大的问题。

因为只有在商品数据更新的时候才会清空缓存,然后才会导致读写并发,但是常规情况下,写操作会小于读操作。这个问题在真实业务系统下问题不大。

学习资料:https://gitee.com/shishan100/Java-Interview-Advanced/blob/master/docs/high-concurrency/redis-consistence.md

https://blog.csdn.net/niulu90/article/details/108266376


This entry was posted in 数据库 and tagged , . Bookmark the permalink.
月小升QQ 2651044202, 技术交流QQ群 178491360
首发地址:月小升博客https://java-er.com/blog/cache-database-different/
无特殊说明,文章均为月小升原创,欢迎转载,转载请注明本文地址,谢谢
您的评论是我写作的动力.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

*