首页 > 数据库 >高级java每日一道面试题-2024年10月13日-数据库篇[Redis篇]-怎么保证缓存和数据库数据的一致性?

高级java每日一道面试题-2024年10月13日-数据库篇[Redis篇]-怎么保证缓存和数据库数据的一致性?

时间:2024-10-13 09:51:19浏览次数:10  
标签:10 面试题 缓存 删除 数据库 更新 一致性 数据

如果有遗漏,评论区告诉我进行补充

面试官: 怎么保证缓存和数据库数据的一致性?

我回答:

在分布式系统中,保证缓存和数据库数据的一致性是一个常见的挑战。由于缓存的引入主要是为了提高系统的性能和响应速度,但这也带来了数据一致性的问题。以下是一些常用的方法来保证缓存和数据库之间的一致性:

缓存更新策略

先更新数据库,再更新缓存
  • 流程:当需要更新数据时,首先更新数据库,然后更新缓存。
  • 优点:实现简单,易于理解。
  • 缺点:存在风险,如果在更新缓存之前系统发生故障,会导致缓存中的数据与数据库不一致。此外,如果更新操作有延迟,也可能导致数据不一致。
先删除缓存,再更新数据库
  • 流程:在更新数据之前,先删除缓存中的数据,然后更新数据库。
  • 优点:可以避免在更新数据库后,缓存中的数据还是旧数据的问题。
  • 缺点:在并发场景下可能会出现问题。例如,一个线程删除了缓存后,另一个线程在缓存被更新之前读取了数据库中的旧数据并写入了缓存,导致数据不一致。
先更新数据库,再删除缓存
  • 流程:首先更新数据库中的数据,然后删除缓存中的数据。
  • 优点:减少了缓存更新失败导致的数据不一致风险。
  • 缺点:在极端并发场景下,仍可能出现数据不一致问题。例如,一个线程更新数据库后,另一个线程在缓存被删除之前读取了数据库中的新数据并写入了缓存(虽然这种情况理论上很难发生,但仍需考虑)。
读写穿透(Read-Through/Write-Through)
  • 流程
    • 读穿透(Read-Through):当从缓存中读取数据时,如果数据不存在,则从数据库中加载数据,并将其放入缓存中。
    • 写穿透(Write-Through):当向缓存中写入数据时,同时将数据写入数据库。
  • 优点:简单且易于实现,保证数据一致性。
  • 缺点:每次读写操作都涉及数据库,可能导致数据库压力增大。
    这种方法可以确保缓存和数据库之间的数据一致,但在高并发场景下可能会导致数据库压力较大。
读写旁路(Read-Around/Write-Around)
  • 流程
    • 读旁路(Read-Around):直接从数据库读取数据,而不经过缓存。
    • 写旁路(Write-Around):直接将数据写入数据库,而不经过缓存。
  • 优点:减少了对数据库的压力,适合不频繁更新的数据。
  • 缺点:缓存中的数据可能不是最新的,需要额外的逻辑来处理数据一致性。
    这种方法适用于某些特定场景,例如某些数据不需要频繁访问或更新。
Canal监听MySQL的Binlog
  • 流程:通过Canal监听MySQL的Binlog写入日志,然后将写入操作(增加、删除和修改)的信息发送至Kafka等消息队列,程序监听到消息队列的消息后更新Redis缓存,从而保证数据的最终一致性。
  • 优点:可以实现数据的最终一致性,且对业务代码的侵入性较小。
  • 实现:需要配置MySQL的Binlog、安装并配置Canal以及编写监听Kafka消息并更新Redis缓存的代码。

缓存失效策略

主动失效(Cache Invalidation)
  • 流程
    • 删除缓存:当数据库中的数据发生变化时,主动删除或更新相应的缓存条目。
    • 设置过期时间:为缓存条目设置一个合理的过期时间,使得缓存在一段时间后自动失效。
  • 主动失效
    • 优点:实时性强,数据一致性好。
    • 缺点:需要处理缓存和数据库之间的同步问题,增加了复杂性。
  • 设置过期时间
    • 优点:简单易用,减轻了数据库的压力。
    • 缺点:可能存在短暂的数据不一致情况。
延迟双删
  • 流程
    • 第一次删除:在更新数据库之前先删除缓存。
    • 第二次删除:更新数据库后,等待一段时间再删除一次缓存,以防止在这段时间内有新的请求重新填充了旧数据到缓存中。
  • 优点:通过延迟再次删除缓存,可以确保在并发场景下,即使有其他线程在缓存被更新之前读取了数据库中的旧数据并写入了缓存,也会被后续的延迟删除操作清除掉。
  • 缺点:延迟时间的设置是一个难点。如果延迟时间过短,可能无法覆盖所有并发场景;如果延迟时间过长,则可能导致在延迟期间内缓存中的数据一直是旧的。

消息队列

  • 流程:使用消息队列来异步处理缓存和数据库的数据同步问题。当数据库发生变更时,发送一条消息到消息队列,消费者接收到消息后再去更新缓存。
  • 优点:可以提高更新的可靠性和性能,解耦系统组件,平滑流量峰值,支持异步处理。避免因为缓存更新失败而导致的数据库和缓存数据不一致问题。
  • 缺点:增加了系统的复杂性,需要处理消息丢失和重复消费等问题。
  • 实现:可以使用如Kafka、RabbitMQ等消息队列中间件来实现。

分布式锁

  • 流程:在更新数据库和缓存的过程中使用分布式锁,确保同一时间只有一个线程能够执行该操作,从而避免并发问题。
  • 优点:确保在同一时间只有一个线程可以修改数据,避免并发问题。可以确保在并发场景下数据的一致性。
  • 缺点:增加了系统的复杂性和开销,可能影响性能。
  • 实现:可以使用如Redis的分布式锁功能来实现。

事务管理

  • 流程:使用分布式事务来保证缓存和数据库的一致性。例如,使用两阶段提交(2PC)或三阶段提交(3PC)协议来确保多个资源的一致性。
  • 优点:提供强一致性保证,适合对数据一致性要求非常高的场景。
  • 缺点:增加了系统的复杂性,可能影响性能,特别是在高并发环境下。

基于版本号或时间戳

  • 流程
    • 乐观锁:在数据中添加版本号或时间戳字段,在更新数据时检查版本号或时间戳是否匹配,如果不匹配则拒绝更新。
    • 悲观锁:在读取数据时锁定数据,直到数据更新完成后再释放锁。
  • 优点:可以在一定程度上保证数据的一致性,适合乐观锁机制。
  • 缺点:需要额外的字段来存储版本号或时间戳,增加了数据模型的复杂性。

延迟加载

  • 流程:对于一些不经常更新的数据,可以采用延迟加载的方式,即只有在首次访问时才从数据库加载数据到缓存中。
  • 优点:减少了不必要的缓存更新,提高了缓存的命中率。
  • 缺点:初始访问时可能会有延迟,用户体验可能受影响。

总结

  • 缓存更新策略:先更新数据库,再删除缓存、先删除缓存,再更新数据库、先更新数据库,再更新缓存、如读写穿透、读写旁路、Canal监听MySQL的Binlog等。
  • 缓存失效策略:如主动失效、设置过期时间、延迟双删等。
  • 消息队列:异步处理数据同步。
  • 分布式锁:避免并发问题。
  • 事务管理:使用分布式事务。
  • 基于版本号或时间戳:乐观锁和悲观锁。
  • 延迟加载:减少不必要的缓存更新。

选择合适的方法取决于具体的应用场景和需求。在实际应用中,通常会结合多种方法来实现最佳的一致性和性能

标签:10,面试题,缓存,删除,数据库,更新,一致性,数据
From: https://blog.csdn.net/qq_43071699/article/details/142893606

相关文章

  • 2024-2025-1 20241310 《计算机基础与程序设计》第三周学习总结 链接
    学期(如2024-2025-1)学号(如:20241300)《计算机基础与程序设计》第X周学习总结作业信息这个作业属于哪个课程2024-2025-1-计算机基础与程序设计这个作业要求在哪里2024-2025-1计算机基础与程序设计第一周作业这个作业的目标自学教材计算机科学概论(第七版)第2章,第3章......
  • 高级java每日一道面试题-2024年10月11日-数据库篇[Redis篇]-Redis都有哪些使用场景?
    如果有遗漏,评论区告诉我进行补充面试官:Redis都有哪些使用场景?我回答:Redis是一个开源的、基于键值对的数据结构存储系统,,它支持多种数据类型,包括字符串、散列、列表、集合和有序集合。它可以用作数据库、缓存和消息中间件。由于其高性能、丰富的数据结构支持以及多种......
  • Python从0到100(六十三):Python OpenCV-入门基础知识
    前言:零基础学Python:Python从0到100最新最全教程。想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Python爬虫、Web开发、计算机视觉、机器学习、神经网络以及人工智能相关知......
  • Springboot在线学习辅导管理系统--49101(免费领源码)可做计算机毕业设计JAVA、PHP、爬虫
    摘 要信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对在线学习辅导管理系统等问题,对在线学习辅导管理系统进行研究分析,然后开发设计出在线学习辅......
  • 2024java最新面试题-10张图!彻底搞定Java线程状态转换
    Java线程状态有几个?Java线程状态是如何转换?Java线程状态转换什么情况会进入锁的等待队列?Java线程状态转换什么情况会进入锁的同步队列?一提到Java线程状态,不少读者立马想到线程状态转换图,但细想,印象又不深刻,只记得有那么几个状态。再要你说出Java线程状态是如何转换的,脑子里......
  • 2024.10.12
    根据你提供的MyBatis配置文件,确实有一个小问题需要注意:驼峰命名配置你已将mapUnderscoreToCamelCase设置为注释(<!--<settingname="mapUnderscoreToCamelCase"value="true"/>-->),这意味着驼峰命名转换功能被禁用了。为了启用它,你需要取消注释并确保该设置的值为true。修......
  • 代码随想录Day24 | LeetCode 122. 买卖股票的最佳时机 II、LeetCode 55. 跳跃游戏、Le
    LeetCode122.买卖股票的最佳时机IIclassSolution:defmaxProfit(self,prices:List[int])->int:res=0foriinrange(1,len(prices)):res+=max(0,prices[i]-prices[i-1])returnresLeetCode55.跳跃游戏class......
  • 【论文速看】DL最新进展20241011-3D雷达、目标检测、大核CNN
    目录【3D雷达】【目标检测】【CNN】【3D雷达】[ECCV2024]BetterCallSAL:TowardsLearningtoSegmentAnythinginLidar论文链接:https://arxiv.org/pdf/2403.13129代码链接:https://github.com/nv-dvl/segment-anything-lidar文中提出了SAL(Lidar中的任意......
  • 20241012 mysql查漏补缺
    2024/10/12mysql查漏补缺1.联合索引什么时候会失效[联合索引]遵循最左前缀法则NO1​ 如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。如果跳跃某一列,索引将会部分失效​ 对于最左前缀法则指的是,查询时,最左边......
  • 第109天:免杀对抗-PowerShell&混淆&分离加载&特征修改&EXE生成&填充替换
    知识点知识点:1、Powershell-对变量数据做文章2、Powershell-对Shellcode做文章3、Powershell-对执行代码特征做文章章节点:编译代码面-ShellCode-混淆编译代码面-编辑执行器-编写编译代码面-分离加载器-编写程序文件面-特征码定位-修改程序文件面-加壳花指令-资源代码......