Redis一致性与分布式锁

Redis一致性

何为redis一致性

即在项目中,redis缓存中的数据要与数据库当中的数据保持一致。

那么这里,就会有小伙伴要问了,redis缓存中的数据不就是从数据库当中查询出来的吗?怎么会不一致呢?

笔者在这里解答一下这个问题嘿嘿,在简单项目中,redis一致性确实不用太过考虑,可是在高并发的项目中,就必须考虑redis的一致性了,举个很简单的例子,比如某平台发起了一个1元抢iphone15的活动,总共只有一台,但却又数万人守在电脑面前跃跃欲试。我们来设想一下,假如成功抢到的那个用户,点击抢购按钮后,是不是redis缓存中的手机数量就给删除了,就没得抢了嘛,然后后台数据库也要进行更新,将可以秒杀的手机数量变为0是不是?

但我们在现实开发过程中,必须要考虑一个很现实的问题:网络波动

我们假设在第一个用户点下抢购按钮,也的确将redis缓存中的秒杀手机这一数据给删除了,但是在将redis的数据更新到数据库这一过程中,产生了网络波动,导致更新操作一直未完成。就在这个网络波动的时间段内,又有一个用户点击了抢购按钮,此时他的请求发到服务器后,服务器发现redis缓存没有秒杀手机数量的数据,于是便会去查询数据库,但此时数据库中的数据并未更新,可供秒杀的手机数量仍然为1,便将这个数据返回给redis,并且这个用户也会显示抢购成功。虽然后面网络波动结束,数据库成功更新了,不会再有任何用户秒杀到手机,但明明只有一台的名额,却有两个用户秒杀到了,这个明显是有问题的,这也就是redis一致性要解决的。

为什么会有redis一致性

在微服务分布式项目中,可能存在数据库更新了,但redis未更新,从而使得客户端所得到的数据(客户端数据从redis缓存当中获取),与后台实际数据库当中的数据不一致的问题。即当高并发的情况下,存在多个用户同时发起一个请求,都需要查询redis中的数据。

上述也有举例,大家可以结合起来理解。

双删一致性

现在我们再假设一个业务场景:

图灵解读:现在有两个线程,分别为线程1和线程2,首先线程1对redis缓存中的数据进行删除,并对数据库进行对应的更新,但由于网络延迟,数据库并未及时更新;与此同时,在网络延迟的时间中,线程2想从redis中查询数据,但由于线程1删除了redis缓存中的数据,所以便会向数据库直接查询,但由于网络延迟,线程1发起的数据库更新操作还未实现,故此时线程2通过redis从数据库中查询到的数据为旧数据,并此旧数据还会存储在redis中,当线程1更新数据库的操作完成之后,此时redis缓存中的数据便与数据库中的数据完全不一致了,并当后续更多线程来查询数据时,也都是会从redis中查询到旧数据

解决方案(双删一致性流程):

即在上述的业务的场景中,我们在线程一对数据的更新操作完成了之后,将当前redis缓存中的数据进行一个删除,这样后续的查询请求便会直接查询数据库当中的最新数据,并将最新的数据存入redis缓存中;因为一共删除了两次数据,即线程1删除了一次,并且线程1对数据库的更新操作执行完成之后,又删除了一次redis,故叫做双删一致性

双删一致性注意点:

在第二次删除的时候,我们需要延迟几百毫秒再进行删除。原因:避免因为线程2将数据库中的老数据放入到redis这一过程产生延迟,导致线程1的第二次删除redis缓存这一操作发生在线程2将老数据放入redis之前,导致redis中仍旧保存的是数据库中到的老数据

双写一致性

流程:

先操作数据库,再删除redis;即数据库中的数据发生了更新后,redis缓存中的数据也要进行一致的更新

如何实现:

方案:如果对实际业务的影响不大,则不管;如果对实际业务有较大影响,则可通过双删来处理

分布式锁

定义

单体项目实现分布式锁:在单进程(启动一个jvm)的系统中,当存在多个线程可以同时改变某个变量(可变共享变量)时,就需要对变量或代码块做同步,使其在修改这种变量时能够线性执行消除并发修改变量。而同步的本质是通过锁来实现的;即多个线程共用一把锁,锁只能被一个线程使用,其余线程只能排队等待使用。

基于数据库操作

乐观锁

定义

乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回给用户错误的信息,让用户决定如何去做

如何使用

表中添加一个时间戳或者版本号的字段来实现,update account set version = version + 1 where id = #{id} and version = #{oldVersion} 当更新不成功,客户端重试,重新读取最新的版本号或时间戳,再次尝试更新,类似 CAS 机制,推荐使用。

悲观锁

定义

假设在并发的情况下,数据处理很容易发生冲突。为了保证数据的一致性和完整性,故每次在读写数据的时候都会先加锁

如何使用

适合于写比较多的操作,先加上锁保证数据的完整和一致性,其余进程等待即可,通过悲观锁锁上,业务需求的强一致性较高,则可以通过悲观锁先锁上,然后一个进程一个进程的进行数据的操作

基于redis缓存与过期时间

redisson执行流程

图文解读

多个线程竞争一个锁,最终只能有一个线程获取到这个锁。通过uuid与线程id作为加锁的key,保证当前锁与当前线程的正确绑定,在线程进行业务处理的时候,内部会有一个watch dog,也就是常说的看门狗机制,它会每隔10s去看一下该线程是否还持有锁,如果还持有的话,则延迟生存时间,给锁进行续命,如果redis进行了集群的话,还会通过lua脚本来进行redis的选择;如果没有获取锁,则会进行自旋,直到成功获取锁 

面试重点题

当redis使用集群时,如果主节点master挂了,如何保持数据的一致性?

答:通过redisson提供的red lock来进行解决,red lock功能:针对redis中的所有节点进行同步,所有节点同步成功后,才会返回锁存储成功,从而达成强一致性。

基于zookeeper临时节点与watch

公平锁

非公平锁

根据Zookeeper的临时节点的特性实现分布式锁,先执行的线程在zookeeper创建一个临时节点,代表获取到锁,后执行的线程需要等待,直到临时节点被删除说明锁被释放,第二个线程可以尝试获取锁。

写在最后:

本篇文章给大家介绍了些redis一致性的知识点,希望能够给大家带来帮助。笔者小,中,大厂均有面试经验,目前正在从事全栈开发工作,坚持每日分享java全栈开发知识与相关的面试真题,希望能够给大家带来帮助,同大家共同进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/49528.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unite 上海 强势回归

​​​ 他回归了 Unite 大会是一年一度的 Unity 全球开发者盛会。今年,Unite 将于 7 月盛夏点亮上海外滩。此次盛会,我们将以“团结”为核心,凝聚全球 3000 多位 Unity 社区精英的力量,共同开启 Unity 技术的新纪元。 在这里&am…

UE学习笔记--干货满满!FString 的 Equals 和 == 源码深度探析

目录 前言FString 的 operatorESearchCaseStricmpBothAsciiLowerAsciiStricmp 结论Stricmp 代码验证整理思路 前言 最近大概写了如下代码 TArray<FString> TestArray; FString Z1 "Z1", z1 "z1"; TestArray.Emplace(Z1);if(TestArray.Contains(z…

代码随想录第十七天|动态规划(1)

目录 LeetCode 509. 斐波那契数列 LeetCode 70. 爬楼梯 LeetCode 746. 使用最小花费爬楼梯 LeetCode 62. 不同路径 LeetCode 63. 不同路径 II 总结 动态规划在算法课上学习过&#xff0c;看过了之后有一些熟悉感。&#xff08;虽然贪心算法也学过&#xff0c;但是不如动态…

样式迁移及代码

一、定义 1、使用卷积神经网络&#xff0c;自动将一个图像中的风格应用在另一图像之上&#xff0c;即风格迁移&#xff1b;两张输入图像&#xff1a;一张是内容图像&#xff0c;另一张是风格图像。 2、训练一些样本使得样本在一些cnn的特征上跟样式图片很相近&#xff0c;在一…

Java字符串与Unicode编码(码点、代码单元、基本多语言平面BMP、辅助平面、代理对)

Java字符串与Unicode编码 1. Unicode编码简介 Unicode是一个为世界上所有书写系统设计的字符编码标准。它旨在解决不同编码标准之间不兼容的问题&#xff0c;使得计算机能够处理和显示世界上几乎所有的字符。Unicode为每个字符分配了一个唯一的数字&#xff0c;称为“码点”&…

字典集合案例

1.统计字符 统计字符串中每个字符出现的次数 s l like summer very much #去掉空格 s s.replace(" ","") d dict() for i in s:if i in d:d[i] 1else:d[i] 1 for i in d:print(i,d[i]) 2.求不重复的随机数 #导入随机数 import random a int(input(&q…

自动化测试的艺术:Xcode中GUI测试的全面指南

自动化测试的艺术&#xff1a;Xcode中GUI测试的全面指南 在软件开发过程中&#xff0c;图形用户界面&#xff08;GUI&#xff09;测试是确保应用质量和用户体验的关键环节。Xcode&#xff0c;作为苹果的官方集成开发环境&#xff08;IDE&#xff09;&#xff0c;提供了一套强大…

智能疲劳驾驶检测:基于YOLO和深度学习的全流程实现

引言 疲劳驾驶是导致交通事故的重要原因之一。为了提高道路安全&#xff0c;及时检测和预警驾驶员的疲劳状态显得尤为重要。本文介绍了一种基于深度学习的疲劳驾驶检测系统。该系统利用YOLO模型&#xff08;YOLOv8/v7/v6/v5&#xff09;进行疲劳驾驶检测&#xff0c;并提供了详…

OD C卷 - 密码输入检测

密码输入检测 &#xff08;100&#xff09; 给定一个密码&#xff0c;‘<’ 表示删除前一个字符&#xff0c;输出最终得到的密码&#xff0c;并判断是否满足密码安全要求&#xff1a; 密码长度>8;至少包含一个大写字母&#xff1b;至少包含一个小写字母&#xff1b;至少…

探索若依(Ruoyi):开源的企业级后台管理系统解决方案

探索若依&#xff08;Ruoyi&#xff09;&#xff1a;开源的企业级后台管理系统解决方案 在现代企业管理中&#xff0c;拥有一个高效、稳定的后台管理系统是至关重要的。若依&#xff08;Ruoyi&#xff09;作为一款开源的企业级后台管理系统&#xff0c;为企业提供了丰富的功能…

SpringBoot中JSR303校验

JSR是 Java EE 的一种标准&#xff0c;用于基于注解的对象数据验证。在Spring Boot应用中&#xff0c;你可以通过添加注解直接在POJO类中声明验证规则。这样可以确保在使用这些对象进行操作之前&#xff0c;它们满足业务规则。个人认为非常有用的&#xff0c;因为它减少了代码中…

2.6基本算法之动态规划2989:糖果

描述 由于在维护世界和平的事务中做出巨大贡献&#xff0c;Dzx被赠予糖果公司2010年5月23日当天无限量糖果免费优惠券。在这一天&#xff0c;Dzx可以从糖果公司的N件产品中任意选择若干件带回家享用。糖果公司的N件产品每件都包含数量不同的糖果。Dzx希望他选择的产品包含的糖…

被问到MQ消息已丢失,该如何处理?

在分布式系统中&#xff0c;消息中间件&#xff08;如 RabbitMQ、RocketMQ、Kafka、Pulsar 等&#xff09;扮演着关键角色&#xff0c;用于解耦生产者和消费者&#xff0c;并确保数据传输的可靠性和顺序性。尽管我们通常会采取多种措施来防止消息丢失&#xff0c;如消息持久化、…

【Vue实战教程】之 Vue Router 路由详解

Vue Router路由 1 路由基础 1.1 什么是路由 用Vue.js创建的项目是单页面应用&#xff0c;如果想要在项目中模拟出来类似于页面跳转的效果&#xff0c;就要使用路由。其实&#xff0c;我们不能只从字面的意思来理解路由&#xff0c;从字面上来看&#xff0c;很容易把路由联想…

HTML(五)——HTML区块,布局

HTML区块 HTML可以通过 <div> 和 <span>将元素组合起来&#xff0c;可以来布局&#xff0c;就是盒子&#xff0c;div是块级盒子&#xff0c;里面 可以放任何东西&#xff0c;span里面装的是文本 HTML 区块元素 大多数 HTML 元素被定义为块级元素或内联元素。 实…

Java 面试 | Redis

目录 1. 在项目中缓存是如何使用的&#xff1f;2. 为啥在项目中要用缓存&#xff1f;3. 缓存如果使用不当会造成什么后果&#xff1f;4. redis 和 memcached 有什么区别&#xff1f;5. redis 的线程模型是什么&#xff1f;6. 为什么单线程的 redis 比多线程的 memcached 效率要…

dns逆向解析,主从服务,多域名访问(穿插ntp服务器)

复习 域名解析&#xff1a; 正向解析&#xff1a;将域名解析为ip 反向解析&#xff1a;将ip解析为域名 逆向解析 关闭防火墙和selinux&#xff0c;配置静态ip [rootdns ~]# vim /etc/named.rfc1912.zones [rootdns ~]# vim /etc/named.conf [rootdns ~]# cd /var/named/ [rootd…

【电子数据取证】了解数据库

文章关键词&#xff1a;电子数据取证、数据库取证、手机取证 一、前言 数据库是信息系统中不可或缺的部分。无论是取证收集&#xff0c;网站重建又或是开发程序都离不开数据库这个角色。 可能你已经或多或少看到过像是MySQL、Redis、MongoDB之类的程序&#xff0c;这些程序统…

前端:Vue学习-4

前端&#xff1a;Vue学习-4 1. 组件缓存 keep-alive2. 状态管理工具 - Vuex2.1 vuex 提供数据&使用数据 - mapState2.2 mutations 修改数据 - mapMutations2.3 actions - 异步操作 - mapActions2.4 getters - 计算属性 - mapGetters 3. Vuex 模块 modules - state,mutation…

day07:用户下单、订单支付

文章目录 地址薄相关相关代码需求分析和设计代码书写 用户下单需求分析和设计代码开发 订单支付微信支付介绍微信支付准备工作如何保证数据安全&#xff1f;如何调用到商户系统 地址薄相关相关代码 需求分析和设计 产品原型接口设计数据库设计 代码书写 地址薄相关代码都是单…