千家信息网

如何解决项目实际应用中redis缓存与数据库一致性问题

发表于:2025-11-17 作者:千家信息网编辑
千家信息网最后更新 2025年11月17日,这篇文章将为大家详细讲解有关如何解决项目实际应用中redis缓存与数据库一致性问题,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、 问题解决思路能否做到先发出的请
千家信息网最后更新 2025年11月17日如何解决项目实际应用中redis缓存与数据库一致性问题

这篇文章将为大家详细讲解有关如何解决项目实际应用中redis缓存与数据库一致性问题,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

一、 问题解决思路

能否做到先发出的请求一定先执行完成呢?常见的思路是"串行化"


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

1service的上游是多个业务应用,上游发起请求对同一个数据并发的进行读写操作,上例中并发进行了一个uid=1的余额修改(写)操作与uid=1的余额查询(读)操作

2service的下游是数据库DB,假设只读写一个DB

3)中间是服务层service,它又分为了这么几个部分

3.1)最上层是任务队列

3.2)中间是工作线程,每个工作线程完成实际的工作任务,典型的工作任务是通过数据库连接池读写数据库

3.3)最下层是数据库连接池,所有的SQL语句都是通过数据库连接池发往数据库去执行的

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

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连接池

}

提问:任务队列其实已经做了任务串行化的工作,能否保证任务不并发执行?

答:不行,因为

11个服务有多个工作线程,串行弹出的任务会被并行执行

21个服务有多个数据库连接,每个工作线程获取不同的数据库连接会在DB层面并发执行

提问:假设服务只部署一份,能否保证任务不并发执行?

答:不行,原因同上

提问:假设1个服务只有1条数据库连接,能否保证任务不并发执行?

答:不行,因为

11个服务只有1条数据库连接,只能保证在一个服务器上的请求在数据库层面是串行执行的

2)因为服务是分布式部署的,多个服务上的请求在数据库层面仍可能是并发执行的

提问:假设服务只部署一份,且1个服务只有1条连接,能否保证任务不并发执行?

答:可以,全局来看请求是串行执行的,吞吐量很低,并且服务无法保证可用性

完了,看似无望了,

1)任务队列不能保证串行化

2)单服务多数据库连接不能保证串行化

3)多服务单数据库连接不能保证串行化

4)单服务单数据库连接可能保证串行化,但吞吐量级低,且不能保证服务的可用性,几乎不可行,那是否还有解?

退一步想,其实不需要让全局的请求串行化,而只需要"让同一个数据的访问能串行化"就行。

在一个服务内,如何做到"让同一个数据的访问串行化",只需要"让同一个数据的访问通过同一条DB连接执行"就行。

如何做到"让同一个数据的访问通过同一条DB连接执行",只需要"在DB连接池层面稍微修改,按数据取连接即可"

获取DB连接的CPool.GetDBConnection()【返回任何一个可用DB连接】改为

CPool.GetDBConnection(longid)【返回id取模相关联的DB连接】

这个修改的好处是:

1)简单,只需要修改DB连接池实现,以及DB连接获取处

2)连接池的修改不需要关注业务,传入的id是什么含义连接池不关注,直接按照id取模返回DB连接即可

3)可以适用多种业务场景,取用户数据业务传入user-id取连接,取订单数据业务传入order-id取连接即可

这样的话,就能够保证同一个数据例如uid在数据库层面的执行一定是串行的

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

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

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


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

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

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

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

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

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

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

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

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上。

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

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

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

关于"如何解决项目实际应用中redis缓存与数据库一致性问题"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

数据 服务 数据库 任务 保证 工作 线程 业务 应用 层面 实际 多个 问题 上下 典型 队列 一致 缓存 不行 全局 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 羊秋玲 网络安全 期末 数据库开发哪个城市好 工信部网络技术证书ntc 阜新迅亨互联网科技有限公司 郑州服务器回收费用情况 西工大网络安全毕业生就业 湖南省教育网络安全协会官网 wps怎么做服务器 sql数据库英文数据备份 三金河北网络技术 宁波网络技术转让信息中心 深圳微信软件开发工程师 为什么引入数据库连接池技术 怎样转移华为手机数据库 企业管理系统数据库 现代化软件开发方法 云服务器被提示被管理员关闭 济南服务器机柜租用 重庆服务器续保调试 广州新一代网络技术开发服务标准 dnf手游怎么连接不上服务器 网络技术公司注册经营范围 云服务器安全组规注意事项 瀚海网络技术有限公司诈骗 数据库技术栈有哪些 系统网络技术发展与现状 厦门java软件开发真实流程 企业计算机网络安全 数据库ID能对应名字嘛 网络安全协调联动机制
0