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

2021-08-14 03:02:13  阅读 48 次 评论 16 条

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

稍等稍等,服务可是部署了很多份的,上述方案只能保证同一个数据在一个服务上的访问,在DB层面的执行是串行化的,实际上服务是分布式部署的,在全局范围内的访问仍是并行的,怎么解决呢?能不能做到同一个数据的访问一定落到同一个服务呢?

三、能否做到同一个数据的访问落在同一个服务上?

上面分析了服务层的上下游及内部结构,再一起看一下应用层上下游及内部结构

上图是一个业务应用的上下游及服务内部详细展开,细节如下:

(1)业务应用的上游不确定是啥,可能是直接是http请求,可能也是一个服务的上游调用

(2)业务应用的下游是多个服务

(3)中间是业务应用,它又分为了这么几个部分

(3.1)最上层是任务队列【或许web-例如帮你干了这个事情了】

(3.2)中间是工作线程【或许web-的工作线程或者cgi工作线程帮你干了线程分派这个事情了】,每个工作线程完成实际的业务任务,典型的工作任务是通过服务连接池进行RPC调用

(3.3)最下层是服务连接池,所有的RPC调用都是通过服务连接池往下游服务去发包执行的

工作线程的典型工作流是这样的:

(){

=();//获取任务

//任务逻辑处理,组成一个网络包,调用下游RPC接口ServiceConnectionc=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上。

四、总结

由于数据库层面的读写并发,引发的数据库与缓存数据不一致的问题(本质是后发生的读请求先返回了),可能通过两个小的改动解决:

(1)修改服务Service连接池,id取模选取服务连接,能够保证同一个数据的读写都落在同一个后端服务上

(2)修改数据库DB连接池,id取模选取DB连接,能够保证同一个数据的读写在数据库层面是串行的

(3关于key重建还有2种方案见《缓存与数据库一致性之三:缓存穿透、缓存雪崩》

五、遗留问题

提问:取模访问服务是否会影响服务的可用性?

答:不会,当有下游服务挂掉的时候,服务连接池能够检测到连接的可用性,取模时要把不可用的服务连接排除掉。

本文地址:http://sbxxw.com/post/1436.html
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

发表评论


表情

评论列表