首页 > 数据库 > > redis缓存与数据库一致性问题解决
假设先写数据库,再淘汰缓存:第一步写数据库操作成功,第二步淘汰缓存失败,则会出现DB中是新数据,Cache中是旧数据,数据不一致【如下图:db中是新数据,cache中是旧数据】。

假设先淘汰缓存,再写数据库:第一步淘汰缓存成功,第二步写数据库失败【如下图:cache中无数据,db中是旧数据】。

结论:先淘汰缓存,再写数据库。
先操作缓存,在写数据库成功之前,如果有读请求发生,可能导致旧数据入缓存,引发数据不一致。
写流程:
读流程:
什么情况下可能出现缓存和数据库中数据不一致呢?

在分布式环境下,数据的读写都是并发的,上游有多个应用,通过一个服务的多个部署(为了保证可用性,一定是部署多份的),对同一个数据进行读写,在数据库层面并发的读写并不能保证完成顺序,也就是说后发出的读请求很可能先完成(读出脏数据):
即在数据库层面,后发出的请求4比先发出的请求2先完成了,读出了脏数据,脏数据又入了缓存,缓存与数据库中的数据不一致出现了
能否做到先发出的请求一定先执行完成呢?常见的思路是“串行化”

上图是一个service服务的上下游及服务内部详细展开,细节如下:
工作线程的典型工作流是这样的:
void work_thread_routine(){
Task t = TaskQueue.pop(); // 获取任务
// 任务逻辑处理,生成sql语句
DBConnection c = CPool.GetDBConnection(); // 从DB连接池获取一个DB连接
c.execSQL(sql); // 通过DB连接执行sql语句
CPool.PutDBConnection(c); // 将DB连接放回DB连接池
}提问:任务队列其实已经做了任务串行化的工作,能否保证任务不并发执行?
答:不行,因为
提问:假设服务只部署一份,能否保证任务不并发执行?
答:不行,原因同上
提问:假设1个服务只有1条数据库连接,能否保证任务不并发执行?
答:不行,因为
提问:假设服务只部署一份,且1个服务只有1条连接,能否保证任务不并发执行?
答:可以,全局来看请求是串行执行的,吞吐量很低,并且服务无法保证可用性
完了,看似无望了,
解决方式
这个修改的好处是:
这样的话,就能够保证同一个数据例如uid在数据库层面的执行一定是串行的
稍等稍等,服务可是部署了很多份的,上述方案只能保证同一个数据在一个服务上的访问,在DB层面的执行是串行化的,实际上服务是分布式部署的,在全局范围内的访问仍是并行的,怎么解决呢?能不能做到同一个数据的访问一定落到同一个服务呢?
能否做到同一个数据的访问落在同一个服务上?
上面分析了服务层service的上下游及内部结构,再一起看一下应用层上下游及内部结构

上图是一个业务应用的上下游及服务内部详细展开,细节如下:
工作线程的典型工作流是这样的:
voidwork_thread_routine(){
Task t = TaskQueue.pop(); // 获取任务
// 任务逻辑处理,组成一个网络包packet,调用下游RPC接口
ServiceConnection c = CPool.GetServiceConnection(); // 从Service连接池获取一个Service连接
c.Send(packet); // 通过Service连接发送报文执行RPC请求
CPool.PutServiceConnection(c); // 将Service连接放回Service连接池
}似曾相识吧?没错,只要对服务连接池进行少量改动:
获取Service连接的CPool.GetServiceConnection()【返回任何一个可用Service连接】改为CPool.GetServiceConnection(longid)【返回id取模相关联的Service连接】这样的话,就能够保证同一个数据例如uid的请求落到同一个服务Service上。
由于数据库层面的读写并发,引发的数据库与缓存数据不一致的问题(本质是后发生的读请求先返回了),可能通过两个小的改动解决:
本篇文章的作用在于提出分布式缓存的问题
实现思路还可以是分布式锁,这里只是抛砖引玉
最后的话:我这边给大家整理了一些资料,包括不限于Kafka、Mysql、Tomcat、Docker、Spring、MyBatis、Nginx、Netty、Dubbo、Redis、Netty、Spring cloud、分布式、高并发、性能调优、微服务等架构技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
领取方式→资料领取方式:私信关键词 【架构资料】即可获取!



领取方式→资料领取方式:私信关键词 【架构资料】即可获取!
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69918097/viewspace-3129470/ ,如需转载,请注明出处,否则将追究法律责任。