当前位置: 首页 > news >正文

JAVA面试总结-Redis篇章(四)——双写一致性

JAVA面试总结-Redis篇章(四)——双写一致性

    • 问:redis 做为缓存,mysql的数据如何与redis进行同步呢?
    • 第一种情况,如果你的项目一致性要求高的话 采用以下逻辑
      • 我们应该先删除缓存,再修改数据库,还是先修改数据库,再删除缓存呢,以下有两种情况
        • 1.先删除缓存,再操作数据库
            • 正常情况
            • 异常情况
        • 2.先更新数据库,再操作缓存
            • 正常情况
            • 异常情况
      • 解决办法 :采用延迟双删
    • 问:为什么要删除两次缓存?
    • 由以上可知,先删除缓存,再修改数据库会导致有脏数据产生,采用延时再进行删除缓存,可以避免这种问题产生。
    • 问:为什么要删除两次缓存?
    • 由以上可知,先删除缓存,再修改数据库会导致有脏数据产生,采用延时再进行删除缓存,可以避免这种问题产生。
    • 问:为什么要延时删除?
    • 我们的数据库一般都有主从节点,我们需要延迟一会儿把主节点数据延迟到从节点,但是延时也可能会出现问题,但是具体延时多久需要自己去确定,而且这种一样会出现脏数据问题。
    • 问:有没有其他方案保持数据强一致?
    • 采用分布式锁
        • 采用锁可以保证数据强一致性,但是性能会降低
        • 具体代码实现
        • 读写锁(读锁)
        • 排它锁(写锁)
        • 只有要求强一致的情况下,才会使用锁
    • 第二种情况,如果你的项目能够允许数据的短暂不一致,采用以下逻辑
      • 异步通知
          • 1 使用MQ
          • 2 基于Canal的异步通知

在这里插入图片描述

问:redis 做为缓存,mysql的数据如何与redis进行同步呢?

第一种情况,如果你的项目一致性要求高的话 采用以下逻辑

在这里插入图片描述

我们应该先删除缓存,再修改数据库,还是先修改数据库,再删除缓存呢,以下有两种情况

1.先删除缓存,再操作数据库

正常情况

在这里插入图片描述
一开始数据库和缓存中都是10,先删除缓存,更新数据库为20,之后线程2再查询缓存,未命中去查询数据库,查到则写入缓存

异常情况

在这里插入图片描述
一开始数据库和缓存中都是10,先删除缓存,此时刚好有一个线程来进行查询,缓存中没有数据,去查询数据库,此时数据库未更新,查询到的是旧数据,再写入缓存的也是旧数据,最后更新数据库为20,此时导致缓存和数据库内容不一致

2.先更新数据库,再操作缓存

正常情况

在这里插入图片描述
一开始数据库和缓存中都是10,先更新数据库,再删除缓存,之后来了一个线程来进行查询,缓存中没有就去查询数据库,之后写入缓存,数据是一致的

异常情况

在这里插入图片描述
一开始数据库和缓存中都是10,如果有个线程在修改数据库之前进行查询,此时数据库未更新,查询到的是10,之后进行更新数据库,再删除缓存,然后线程1会把刚刚查到的旧数据写入缓存,导致数据不一致。

解决办法 :采用延迟双删

问:为什么要删除两次缓存?

由以上可知,先删除缓存,再修改数据库会导致有脏数据产生,采用延时再进行删除缓存,可以避免这种问题产生。

问:为什么要删除两次缓存?

由以上可知,先删除缓存,再修改数据库会导致有脏数据产生,采用延时再进行删除缓存,可以避免这种问题产生。

问:为什么要延时删除?

在这里插入图片描述

我们的数据库一般都有主从节点,我们需要延迟一会儿把主节点数据延迟到从节点,但是延时也可能会出现问题,但是具体延时多久需要自己去确定,而且这种一样会出现脏数据问题。

问:有没有其他方案保持数据强一致?

采用分布式锁

在这里插入图片描述

采用锁可以保证数据强一致性,但是性能会降低

在这里插入图片描述

具体代码实现

读写锁(读锁)

在这里插入图片描述

排它锁(写锁)

在这里插入图片描述

只有要求强一致的情况下,才会使用锁

第二种情况,如果你的项目能够允许数据的短暂不一致,采用以下逻辑

异步通知

1 使用MQ

在这里插入图片描述

2 基于Canal的异步通知

在这里插入图片描述
这种方法代码侵入较小

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

http://www.lryc.cn/news/98865.html

相关文章:

  • 赋能医院数字化转型,医院拍摄VR全景很有必要
  • Vue3项目中没有配置 TypeScript 支持,使用 TypeScript 语法
  • 数据可视化大屏拼接屏开发实录:屏幕分辨率测试工具
  • 每日一题7.28 209
  • Python + Playwright 无头浏览器Chrome找不到元素
  • C++信号量与共享内存实现进程间通信
  • [Tools: Camera Conventions] NeRF中的相机矩阵估计
  • 【sgUpload】自定义上传组件,支持上传文件夹及其子文件夹文件、批量上传,批量上传会有右下角上传托盘出现,支持本地上传图片转换为Base64image
  • Kafka 实时处理Stream与Batch的对比分析
  • Andriod开发性能优化实践
  • linux环境安装mysql数据库
  • 【深度学习中常见的优化器总结】SGD+Adagrad+RMSprop+Adam优化算法总结及代码实现
  • 山东大学软件学院考试回忆——大二上
  • 【Express.js】异常分类和日志分级
  • k8s webhook实例,java springboot程序实现 对Pod创建请求添加边车容器 ,模拟istio实现日志文件清理
  • 关于electron的问题汇总
  • ps 给衣服换色
  • AI人工智能未来在哪里?2023年新兴产业人工智能有哪些就业前景?
  • 组件间通信案例练习
  • 【matlab】机器人工具箱快速上手-正运动学仿真(代码直接复制可用)
  • 论文解读|PF-Net:用于 3D 点云补全的点分形网络
  • 网络安全(零基础)自学
  • Spring Security 身份验证的基本类/架构
  • 市值超300亿美金,SaaS独角兽Veeva如何讲好中国故事?
  • 编译内联导致内存泄漏的问题定位修复
  • 基于WebSocket实现的后台服务
  • Go语言中的结构体详解
  • pytest自动化测试指定执行测试用例
  • 英伟达 H100 vs. 苹果M2,大模型训练,哪款性价比更高?
  • var、let和const的区别