小工具      在线工具  汉语词典  css  js  c++  java

REDIS21_Cache双写一致性方案,先更新数据库再删除缓存

REDIS - 高性能缓存,数据库,缓存,redis 额外说明

收录于:199天前

①. 什么是缓存双写一致

  • ①.缓存双写一致性,谈谈你的理解
  1. 如果redis中有数据,需要和数据库中的值一致
  2. 如果redis中没有数据,则数据库中的值一定是最新值
  • ②. 什么时候同步直写?
    小数据,某条、某一小戳热点数据,要求立刻变更,可以前台服务降价一下,后台马上同步直写

  • ③.异步延迟写什么时候进行?

  1. 正常业务,立即更新mysql,业务容忍1小时后redis生效。
  2. 异常发生后,失败的action需要重新打补丁,需要使用Kafka或者RabbitMQ等消息中间件来实现解耦和重试重写。

②. 先更新数据库,再更新缓存

  • ①.首先更新mysql中某个产品的库存。该产品当前库存为 100 件,更新为 99 件。

  • ②.先成功更新mysql到99,然后更新redis

  • ③.假设此时出现异常,redis更新失败。这导致mysql中的库存为99,但redis中的库存仍然是100。

  • ④.如果出现上述情况,就会导致数据库和缓存的redis中的数据不一致,读取到脏数据。

③. 先删除缓存,再更新数据库

  • ①.线程A首先成功删除redis中的数据,然后更新mysql。此时mysql正在更新,还没有结束。 (比如网络延迟)B突然出现读取缓存数据。

  • ②.此时redis中的数据为空。线程B来读取它。它首先读取redis中的数据(已经被线程A删除了)。这里出现两个问题:

  1. B从mysql获取旧值:线程B发现redis中没有(缓存丢失),立即在mysql中读取。旧值是从数据库中读取的。
  2. B将获取到的旧值写回redis:获取到旧值数据后,返回前台,写回redis(线程A刚删除的旧数据很有可能又被写回)
  • ③.线程A更新完mysql后,发现redis中的缓存是脏数据。

  • ④.流程总结

  1. 请求A执行写操作。删除缓存后,工作正在进行中……A已经完全更新了吗?
  2. 请求B开始工作,查询redis发现缓存不存在
  3. 请求B继续并查询数据库以获取myslq中的旧值
  4. 请求B将旧值写入redis缓存
  5. 请求B将旧值写入redis缓存
    在这里插入图片描述
  • ⑤.采用延迟双删除策略:
    添加睡眠期的目的是让线程B先从数据库中读取数据,然后将缺失的数据写入缓存,然后线程A将其删除。因此,线程A休眠的时间需要大于站点B读取数据然后写入缓存的时间。这样,当其他线程读取数据时,就会发生缓存未命中,因此会从数据库中读取最新的值。因为这种方案会在第一次删除缓存值后延迟一段时间删除,所以我们也称之为“延迟双重删除”
    在这里插入图片描述
  • ⑥.这个删除应该休眠多长时间?这个时间怎么确定呢?
  1. 业务程序运行时,统计线程读数据、写缓存的操作时间,自己评估一下自己项目的读数据业务逻辑的耗时,并据此做出估算。那么写数据的休眠时间是根据读数据业务逻辑的时间加上100毫秒。
  2. 这样做的目的是保证读请求结束,写请求可以删除读请求造成的缓存脏数据。
  • ⑦.如果由于这种同步淘汰策略导致吞吐量下降怎么办?异步删除
    在这里插入图片描述

④.先更新数据库,再删除缓存

  • ①.异常原因:如果缓存删除失败或者太晚,再次请求访问redis时缓存命中,读取的是旧的缓存值。
    在这里插入图片描述
  • ②.解决方案
  1. 可以将要删除的缓存值或者要更新的数据库值临时存储在消息队列中(例如使用Kafka/RabbitMQ等)
  2. 当程序未能成功删除缓存值或更新数据库值时,它可以从消息队列中重新读取这些值,然后再次删除或更新它们。
  3. 如果删除或更新能够成功,我们会将这些值从消息队列中移除,以避免重复操作。这时我们还可以保证数据库和缓存的数据一致,否则就需要再次重试。
  4. 如果重试超过一定次数后仍然没有成功,我们需要向业务层发送错误消息并通知运维人员。
    在这里插入图片描述
  • ③.说说为什么要引入MQ
  1. 应用程序将数据更新到数据库后,更新操作会发送到消息队列,然后消息队列异步触发缓存数据的删除。
  2. 这样做的好处是,即使更新数据库后出现异常或者网络延迟,数据更新操作已经放到了消息队列中,不会造成缓存数据与数据库数据不一致。
. . .

相关推荐

额外说明

J2EE项目代码编写规范

  代码编写规范目的:能够在编码过程中实现规范化,为以后的程序开发中养成良好的行为习惯。 代码编写规范使用范围:J2EE项目开发。 包命名规范: 目的:包的命名规范应当体现出项目资源良好的划分 servlet类所在包命名规范:公司名称.开发组名称.项目名

额外说明

实战渗透-fofa-dirBrute-代码审计-构造poc-ueditor-解密-过waf-Godzilla

关键词 —> 目标源码 主域名 没有子域 信息收集 中间件 IIS 8.5 输入admin发现自动添加了/ ------> 说明其目录存在, 盲猜 文件,login.aspx default.aspx main.aspx 等等 最终在login.aspx

额外说明

如何秒下三方Python库

需求背景 直接Pip install并非不能下,但是一般需要中断多次,然后继续断点续传才行,速度也最多20K,愁死个人。 解决方案 豆瓣镜像基本包含了所有常用的py库,反正我要的什么pyqt5-tool这里都有,所以正确的python三方库安装姿势就是:

额外说明

Java Thread 的使用

Java Thread 的使用 原文地址:https://www.cnblogs.com/renhui/p/6066852.html Java Thread 的使用 Java Thread 的 run() 与 start() 的区别 Java Threa

额外说明

ch4_3高速缓冲存储器

1. cache出现的原因 cpu: 处理速度快, 但是存储容量小, 主存: 处理速度低,但是存储容量大; 为了弥补两者之间的差距,  使用了缓存; 要想充分发挥cache 的能力,  需要保证 cpu 所需要的数据和 指令大多数都能够在cache中获取

额外说明

javax.websocket-api 简介、中文文档、中英对照文档 下载

javax.websocket-api 文档 下载链接(含jar包、源码、pom) 组件名称 中文-文档-下载链接 中英对照-文档-下载链接 javax.websocket-api-1.1.jar javax.websocket-api-1.1-API文

额外说明

【Java 进阶篇】深入理解 Bootstrap 导航条与分页条

Bootstrap 是一个强大的前端框架,为网页和应用程序开发提供了丰富的组件和工具。其中,导航条和分页条是两个常用的组件,用于创建网站的导航和分页功能。本篇博客将深入探讨 Bootstrap 导航条和分页条的使用,适用于那些希望提升网页设计技能的初学者

额外说明

Angular开发(二十五)-angular自带动画效果

angular2中使用自带的动画 一、在组件中创建一个动画 import {Component,OnInit,style,trigger,state,transition,animate,keyframes} from '@angular/core';

额外说明

建造者模式(Builder Pattern)

  一、建造者模式简介(Brief Introduction) 建造者模式(Builder Pattern),将一个复杂对象的构建与它的表示分离,使的同样的构建过程可以创建不同的表示。 建造者模式的优点是:使得建造代码与表示代码分离,由于建造者隐藏了该产

额外说明

wordpress漏洞利用_利用WordPress和Facebook功能的优秀教程

WordPress 漏洞利用 Facebook 可以在博客的发展中发挥至关重要的作用,因为它是网络上最大的社交媒体网络之一。在本文中,我们将分享一些最有价值的技巧和教程,让您充分利用 Facebook 和 WordPress 的强大功能。 由于 Face

ads via 小工具