百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

redis缓存使用之三:如何保证数据库的数据和redis数据的一致性

mhr18 2024-10-26 10:46 21 浏览 0 评论

在使用redis做缓存时,会和做分布式事务有同样的问题,就是你没有办法百分之百的保证数据的强一致性,我们只能通过技术的手段,来减少数据不一致的时间

在面试的时候,问到怎么去保证redis数据的一致性,很多人说更新数据库时,同步更新redis,但是用这种方案,无论是先提交数据库在更新redis,或是先更新redis在提交数据库,都会有一方成功但是另一方失败的可能,造成数据的不一致性,而且还有一种可能,两个线程同时去更新,线程a先更新了数据库,然后线程b又去更新了数据库并且把数据更新到了redis,然后线程a又去更新了redis,这样两个线程全部执行结束后,数据库中存的数据是线程b的数据,而redis中存的是线程a的数据,依然会造成数据的不一致性。所以这种方案是不可取的。

还有人说,对redis做先删后插,即更新数据库成功后,提交事务之前,先把redis数据删除,如果删除成功,则提交数据库事务,删除失败,则回滚事务。这样在提交事务后,如果有查询的请求过来,发现redis中的数据已被删掉,则会去数据库查询,将数据库最新的数据在回写到redis,这样就保证了数据的一致性。这种方案貌似看起来是没有问题的,但是其实还是有漏洞的,如果在你删除redis成功之后,数据库提交之前,又有查询的请求过来了,这时发现redis没有数据,会自动去数据库查询,但是由于此时数据库的事务还没有提交,数据库中存的还是旧数据,此时又把旧数据回写到redis了,依然会造成数据的不一致的,针对这种问题的解决方案,有很多人说,加锁,或是加队列,让查询的请求和更新的请求由并行变为串行,就可以解决问题了,但是这种方案就已经违背了我们用redis的初衷,我们用redis做缓存的目的就是为了提高效率,你这又加锁又加队列的,效率反而降下来了,那我们还用redis干嘛呢?

正确的做法是,还是按照上面的先删后插的方案,只不过做了一下改进,做个双删机制,既数据库提交事务之前删一次redis,事务提交之后,在删一次redis,这样的话,即使在事务提交之前,有查询请求将旧数据回写到redis了,我在事务提交之后,在删一次redis,下次查询过来,就由会把新的数据回写到了redis了。

但是这样还是会有个问题,就是说我在事务提交之前,查询请求把旧数据回写到redis了,但是在事务提交之后,我又删除redis失败了,怎么办?这就是我开篇所说的,没有办法去百分之百的保证数据的强一致性,只能尽最大的努力去减少数据不一致的时间,遇到这种情况,你可以采取异步重试的机制,或者依赖于key的过期时间,key过期后会自动从redis中删掉。

那可能有人会问了,按照这种方案的话,是不是只要提交事务之后删一次redis就可以了,在提交事务之前删redis没啥意义啊。但是还是像我开篇所说的,我们要尽最大努力去减少数据不一致的时间,如果只是提交事务之后去删一次,一旦删除失败了,就会造成数据不一致性,只能通过重试机制或key的过期时间来保证它的最终一致性,但是你如果在提交事务之前也删一次,并且提交事务前也没有查询请求将旧数据回写到redis,此时你提交事务后,删除失败了也无所谓,我依然可以保证数据的一致性。那在这种模式下,什么时候会出现数据不一致呢,只有一种情况,你在提交事务之前,redis删除成功了,此时又有查询请求将旧数据库回写到了redis,然后再事务提交成功之后,又redis又失败了。但是大家可以想象一下,这种概率的发生会有多小,对redis做同样的操作,你上一秒还能成功,下一秒就失败咯,此时又偏偏来个查询的请求把旧数据回写到redis了,这种概率的发生,简直太小了,而且即使出现了这种问题也没关系,我们依然可以采用重试机制或者key的过期时间来保证它的最终一致性。

这样的方案看起来是完美了,但是在实现上还是有问题的,我操作数据库和redis都是在dao层,但是事务的提交是在service层控制的,而且service和dao层是隔离的,我在service层提交事务后,我并不知道需要删除redis的哪些数据,而且每写一个接口,都需要去手动调一个删除后redis数据的方法,也是挺麻烦的。这个问题我是这样解决的,在dao层更新数据库成功后,我会把需要删除的redis的key ,放到threadlocal里面,然后在拦截器里面,获取这个threadlocal,去删除redis,而且此时去删除redis,是否删除成功,用户是不需要关心的,所以为了提高接口的响应效率,可以做个异步删除。但是这种说的都是以接口的方式,把获取threadlocal方法和异步删除的方法都写在拦截器了,不需要每次都手工去调,但是如果不以接口的方式,以定时任务的方式,不走拦截器,那这种就只能没次都手工调了。

上面说的方案,都是针对的根据id去操作唯一的一条数据,那如果在业务中,需要根据其他条件,去批量更新数据,怎么办呢,有人说先按照这些条件,把这些数据的id去查询出来,然后一个一个的去删,但是这样会有一个问题,在你查询和更新数据库之间,又有人更新了数据库,导致你查询出来的数据,和实际更新的数据是不一致的,这样就会出现问题,所以个人建议,如果真的有业务场景,还是先把这些数据查询出来,然后一条一条的去根据id做更新,不要去做批量更新,当然了,还是要根据具体业务去决定。

这都是我的一些个人看法,大家如果有不同意见,欢迎评论区讨论,让我们共同进步[微笑]

相关推荐

redis 7.4.3更新!安全修复+性能优化全解析

一、Redis是什么?为什么选择它?Redis(RemoteDictionaryServer)是一款开源的高性能内存键值数据库,支持持久化、多数据结构(如字符串、哈希、列表等),广泛应用于缓存、消...

C# 读写Redis数据库的简单例子

CSRedis是一个基于C#的Redis客户端库,它提供了与Redis服务器进行交互的功能。它是一个轻量级、高性能的库,易于使用和集成到C#应用程序中。您可以使用NuGet包管理器或使用以下命令行命令...

十年之重修Redis原理

弱小和无知并不是生存的障碍,傲慢才是。--------面试者总结Redis可能都用过,但是从来没有理解过,就像一个熟悉的陌生人,本文主要讲述了Redis基本类型的使用、数据结构、持久化、单线程模型...

高频L2行情数据Redis存储架构设计(含C++实现代码)

一、Redis核心设计原则内存高效:优化数据结构,减少内存占用低延迟访问:单次操作≤0.1ms响应时间数据完整性:完整存储所有L2字段实时订阅:支持多客户端实时数据推送持久化策略:RDB+AOF保障数...

Magic-Boot开源引擎:零代码玩转企业级开发,效率暴涨!

一、项目介绍基于magic-api搭建的快速开发平台,前端采用Vue3+naive-ui最新版本搭建,依赖较少,运行速度快。对常用组件进行封装。利用Vue3的@vue/compiler-sfc单文...

项目不行简历拉胯?3招教你从面试陪跑逆袭大厂offer!

项目不行简历拉胯?3招教你从面试陪跑逆袭大厂offer!老铁们!是不是每次面试完都感觉自己像被大厂面试官婉拒的渣男?明明刷了三个月题库,背熟八股文,结果一被问项目就支支吾吾,简历写得像大学生课程设计?...

谷歌云平台:开发者部署超120个开源包

从国外相关报道了解,Google与Bitnami合作为Google云平台增加了一个新的功能,为了方便开发人员快捷部署程序,提供了120余款开源应用程序云平台的支持。这些应用程序其中包括了WordPre...

知名互联网公司和程序员都看好的数据库是什么?

2017年数据库领域的最大趋势是什么?什么是最热的数据处理技术?学什么数据库最有前途?程序员们普遍不喜欢的数据库是什么?本文都会一一揭秘。大数据时代,数据库的选择备受关注,此前本号就曾揭秘国内知名互联...

腾讯云发布云存储MongoDB服务

近日,著名安全专家兼Shodan搜索引擎的创建者JohnMatherly发现,目前至少有35000个受影响的MongoDB数据库暴露在互联网上,它们所包含的数据暴露在网络攻击风险之中。据估计,将近6...

已跪,Java全能笔记爆火,分布式/开源框架/微服务/性能调优全有

前言程序员,立之根本还是技术,一个程序员的好坏,虽然不能完全用技术强弱来判断,但是技术水平一定是基础,技术差的程序员只能CRUD,技术不深的程序员也成不了架构师。程序员对于技术的掌握,除了从了解-熟悉...

面试官:举个你解决冲突的例子?别怂!用这个套路……

面试官:举个你解决冲突的例子?别怂!用这个套路……最近收到粉丝私信,说被问到:团队技术方案有分歧怎么办?当场大脑宕机……兄弟!这不是送命题,是展示你情商+技术判断力的王炸题!今天教你们3招,用真实案例...

面试碰到MongoDB?莫慌,跟面试官这样吹MongoDB 复制集

推荐阅读:吊打MySQL:21性能优化实践+学习导图+55面试+笔记+20高频知识点阿里一线架构师分享的技术图谱,进阶加薪全靠它十面字节跳动,依旧空手而归,我该放弃吗?文末会分享一些MongoDB的学...

SpringBoot集成扩展-访问NoSQL数据库之Redis和MongoDB!

与关系型数据库一样,SpringBoot也提供了对NoSQL数据库的集成扩展,如对Redis和MongoDB等数据库的操作。通过默认配置即可使用RedisTemplate和MongoTemplate...

Java程序员找工作总卡项目关?

Java程序员找工作总卡项目关?3招教你用真实经历写出HR抢着要的简历!各位Java老哥,最近刷招聘软件是不是手都划酸了?简历投出去石沉大海,面试邀请却总在飞别人的简历?上周有个兄弟,13年经验投了5...

Java多租户SaaS系统实现方案

嗯,用户问的是Java通过租户id实现的SaaS方案。首先,我需要理解用户的需求。SaaS,也就是软件即服务,通常是指多租户的架构,每个租户的数据需要隔离。用户可能想知道如何在Java中利用租户ID来...

取消回复欢迎 发表评论: