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

Redis 之四:Redis 事务和乐观锁

事务特点

Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:

  • 批量操作在发送 EXEC 命令前被放入队列缓存。

  • 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。不具备原子性。

  • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

Redis 事务的缺点
  1. 不支持回滚: Redis事务在执行EXEC命令之前,如果通过WATCH检测到监视的键发生了变化,则会拒绝执行整个事务并返回空结果。但请注意,这并不是传统数据库中的“回滚”操作,因为Redis不会自动撤销已经执行过的命令,它仅仅是在事务中止时阻止后续未执行的命令。
  2. 命令排队一次性执行: 在Redis事务中,所有命令会被放入一个队列,在EXEC命令被执行时按照先进先出的顺序执行,期间不能中断或插入新的命令。这意味着事务开始后无法根据中间结果动态调整事务内的操作,降低了灵活性。
  3. 无隔离级别: Redis的事务没有提供如SQL数据库那样的多种事务隔离级别(如读已提交、可重复读等)。所有事务都是在单线程环境下的串行化执行,因此避免了脏读、不可重复读等问题,但这也意味着在高并发场景下可能会有性能瓶颈。
  4. Watch-Multi-Exec模式的问题: 使用WATCH进行乐观锁控制时,一旦网络延迟或者客户端异常导致事务未能及时执行,监视的数据可能已经被其他客户端修改,此时即便事务最终执行,也无法保证数据一致性。
  5. 批量操作不具备完全的原子性: 虽然Redis的所有命令在服务器内部是原子执行的,但在一个事务中多个命令的组合并不能视为一个原子操作。例如,事务中包含对多个key的操作,即使其中一个操作失败,事务内其它命令也会被执行完毕,而不是整体取消。
三个阶段

一个事务从开始到执行会经历以下三个阶段:

  • 开始事务。
  • 命令入队。
  • 执行事务。
案例步骤

从multi 开始,一系列操作,最后执行 exec ,批量执行处理

127.0.0.1:6379> multi
OK
127.0.0.1:6379> keys *
QUEUED
127.0.0.1:6379> hset person name zhang age 34
QUEUED
127.0.0.1:6379> hdel person age
QUEUED
127.0.0.1:6379> hset person email zhang@sina.com
QUEUED
127.0.0.1:6379> exec
1)  1) "listz"2) "book"3) "word"4) "myset"5) "mydest"6) "student"
2) (integer) 2
3) (integer) 1
4) (integer) 1
127.0.0.1:6379> hgetall person
1) "name"
2) "zhang"

下表列出了 redis 事务的相关命令:

序号命令及描述
1[DISCARD] 取消事务,放弃执行事务块内的所有命令。
2[EXEC] 执行所有事务块内的命令。
3[MULTI] 标记一个事务块的开始。
4[UNWATCH] 取消 WATCH 命令对所有 key 的监视。
5[WATCH key [key ...]] 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
乐观锁

乐观锁(Optimistic Locking)是一种在数据库并发控制中的策略,它假设多用户同时访问同一数据时发生冲突的概率较低,并且在更新数据之前并不立即进行加锁操作。与悲观锁不同的是,悲观锁在读取数据时就直接获取并持有锁,直到事务结束才释放;而乐观锁则是:

  1. 读取阶段:当一个事务想要修改数据时,它不会立即锁定该数据行。每个事务在读取数据时都会记录下当时的数据版本号或时间戳等信息。
  2. 验证阶段:在事务提交更新操作前,会再次检查当前要更新的数据是否自上次读取以来没有被其他事务修改过。这通常通过比较数据的版本号来实现,如果版本号未变,则认为可以安全地执行更新。
  3. 更新阶段:如果数据版本验证通过(即版本号仍为事务开始读取时的版本),则执行更新操作,并将数据版本号递增,确保后续的并发事务能够识别出这次更新。如果发现版本号已被改变,说明存在并发修改,此时乐观锁机制会让当前事务回滚,并提示并发错误,通常需要重新读取数据并尝试更新。
Redis 乐观锁

Redis 乐观锁是一种在分布式系统中实现并发控制的机制,它借鉴了数据库领域的乐观并发控制思想,并通过Redis提供的命令来实现。在乐观锁策略下,假定多个客户端同时访问同一数据时,通常不会发生冲突或至少冲突的概率较低。因此,在读取数据时不立即加锁,而是在更新数据前才去检查在此期间是否有其他客户端修改过该数据。

在Redis中,乐观锁主要通过WATCH命令和事务(multi/exec)来实现:

  1. WATCH命令:客户端使用WATCH命令监视一个或多个键,这些键的数据状态将被记录下来。当执行WATCH后,如果任何被监视的键在事务提交前发生了变化,则整个事务将会被打断,即不会执行EXEC命令内的操作。
  2. 事务处理:客户端可以将一系列命令放入事务中,使用MULTI开始一个事务块,然后执行一系列的操作指令。最后,用EXEC命令尝试提交事务。只有在所有被WATCH的键自WATCH以来未被其他客户端改变的情况下,事务中的命令才会被执行。

举例来说:

  • 客户端A对一个键进行WATCH
  • 然后客户端A开始一个事务,并准备修改这个键的值。
  • 在事务提交(EXEC)之前,如果其他客户端改变了该键的值,那么客户端A的事务在执行EXEC时会发现数据已经被修改,从而导致事务回滚,不执行任何操作。

下面具体来举例:

主要是 watch 和 multi 两个命令配合使用,实现乐观锁

watch 监视某一个可能变化的 key。然后开启事务,一系列操作放入队列等待执行,如果在exec 执行事务之前,其他的客户端对监视的key 做了修改,则exec 执行结果为nil 。什么都不执行。

127.0.0.1:6379> watch mm         #### 开始监视 mm 变量
OK
127.0.0.1:6379> multi            #### 开启事务
OK
127.0.0.1:6379> incrby mm 500    #### 第一次 给 mm 加500 操作放入队列
QUEUED
127.0.0.1:6379> incrby mm 500    #### 第二次 给 mm 加500 操作放入队列 
QUEUED
### 此时去另一个客户端执行修改操作

另一个客户端的修改操作

127.0.0.1:6379> decrby mm 500    #### 给 mm 减去500
(integer) -500                   #### 立即起效,结果为 -500

然后再回原来执行事务的客户端执行下面操作:

127.0.0.1:6379> exec             #### 开始执行事务
(nil)                            #### 没有任何执行结果  因为乐观锁起作用了
127.0.0.1:6379> get mm           #### 再次查看结果
"-500"                           #### 是另一个客户端的执行结果。刚才加的两次500 无效。
127.0.0.1:6379> watch mm         #### 再次监控
OK
127.0.0.1:6379> multi            #### 开启事务
OK
127.0.0.1:6379> incrby mm 500    #### 加500
QUEUED
127.0.0.1:6379> incrby mm 500    #### 加500
QUEUED
127.0.0.1:6379> exec             #### 执行事务
1) (integer) 0
2) (integer) 500                 #### 执行成功,因为其他客户端没有修改被监视的变量 mm .
127.0.0.1:6379> 

相关文章:

Redis 之四:Redis 事务和乐观锁

事务特点 Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证: 批量操作在发送 EXEC 命令前被放入队列缓存。 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。不具备原子性。 在事务执…...

C# WPF编程-创建项目

1.创建新项目 选择“WPF应用程序”》“下一步” 设置项目 设置项目名称,保存位置等参数>下一步 3.选择框架 4.项目创建成功 5.运行项目...

密码学及其应用(应用篇15)——0/1背包问题

1 问题背景 背包问题是一个经典的优化问题,在计算机科学和运筹学中有着广泛的应用。具体到你提到的这个问题,它是背包问题中的一个特例,通常被称为0/1背包问题。这里,我们有一系列的正整数 ,以及一个正整数&#xff0c…...

基于springboot+vue的实验室管理系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…...

华为OD技术面试案例5-2024年

背景 985本计算机专业,目标院校。 1.15 投递 在某BOSS上投递的简历,HR人很nice,非常负责任。 1.19 收到机试通知 第一题是一个哈夫曼编码,第三题是一个动态规划,机试整体难度不算高,刷leetcode hot100…...

【QT+QGIS跨平台编译】之五十五:【QGIS_CORE跨平台编译】—【qgsmeshcalcparser.cpp生成】

文章目录 一、Bison二、生成来源三、构建过程一、Bison GNU Bison 是一个通用的解析器生成器,它可以将注释的无上下文语法转换为使用 LALR (1) 解析表的确定性 LR 或广义 LR (GLR) 解析器。Bison 还可以生成 IELR (1) 或规范 LR (1) 解析表。一旦您熟练使用 Bison,您可以使用…...

Unity(第二十部)效果 粒子、线条和拖尾

1、粒子系统 粒子系统介绍 Unity 粒子系统是 Unity 引擎中用于创建和控制粒子效果的工具。它可以模拟各种自然现象,如火焰、烟雾、雨滴等,也可以用于创建特效,如魔法光芒、爆炸效果等。 粒子系统组成 在 Unity 中,粒子系统由发射…...

全量知识系统问题及SmartChat给出的答复 之6 三套工具之1

Q15. 提出想法和问题 前面说过,DDD在我要设计的全量知识系统中位于中间层,是专门用来解决“知识汤”问题的。 解决的思路就是以将为在特定领域中的公司经营提供一个责任-权限平面为目的,帮助他们调整商业模式以及组建恰当的组织&#xff0c…...

[RoarCTF 2019]Easy Calc

这题考查的是: 字符串解析特性目录读取文件内容读取 字符串解析特性详解:PHP字符串解析特性 ($GET/$POST参数绕过)(含例题 buuctf easycalc)_参数解析 绕过-CSDN博客 ascii码查询表:ASCII 表 | 菜鸟工具 …...

完美解决 git 报错fatal: Not a git repository (or any of the parent directories): .git

问题描述 错误提示是找不到.git文件,无法执行git指令,意思是 当前你要提交的文件夹中没有.git这个文件 解决方案 执行如下命令: git init...

electron无法设置自己的图标?渲染进程require报错?

electron无法设置自己的图标? 极有可能是图标太大,或者宽高不同 我推荐的网址icon转换 选着20x20一般就可以 渲染进程无法使用require?一直报错? webPreferences: {nodeIntegration: true, enableRemoteModule: true, contextIsolation: …...

vscode连接服务器与FileZilla上传到服务器

https://www.cnblogs.com/qiuhlee/p/17729647.html(这个是vscode连接服务器) 主机:就是服务器的主机号 使用者名称:比如ALmax的用户名 密码:比如ALmax的密码...

练习 1 Web EasySQL极客大挑战

CTF Week 1 EasySQL极客大挑战 BUUCTF 典中典复习 Web SQL 先尝试输入,找一找交互页面 check.php 尝试万能语句 a’ or true SQL注入:#和–的作用 get传参只能是url编码,注意修改编码,输入的字符串要改成url格式。 POST请求和…...

matlab生成模拟的通信信号

matlab中rand函数生成均匀随机分布的随机数,randn生成正态分布的随机数; matlab来模拟一个通信信号; 通信信号通过信道时,研究时认为它会被叠加上服从正态分布的噪声; 先生成随机信号模拟要传输的信号,s…...

Altair® SimLab® 以流程为导向的多学科仿真环境,可连接CAD 的多物理场工作流程

Altair SimLab 以流程为导向的多学科仿真环境,可连接CAD 的多物理场工作流程 SimLab 是一种以流程为导向的多学科仿真环境,能够精确分析复杂装配体的性能表现。包括结构、热和流体动力学在内的多物理场可以通过高度自动化的建模任务轻松设置,有助于大幅…...

Python爬虫-爬取B站番剧封面

本文是本人最近学习Python爬虫所做的小练习。如有侵权,请联系删除。 页面获取url 代码 import requests import os import re# 创建文件夹 path os.getcwd() /images if not os.path.exists(path):os.mkdir(path)# 当前页数 page 1 # 总页数 total_page 2# 自动…...

AI时代的产品文案秘籍:如何用AI提升效率

人工智能写作工具:解放双手,创作不停歇 在当前人工智能技术飞速发展的背景下,越来越多的个体已经开始利用这一AI写作工具,以显著提高自己的工作效率。这不仅标志着人工智能服务于人类的宏伟时代的到来,更是人人可用的创…...

前端架构: 脚手架通用框架封装之入口文件开发(教程一)

脚手架入口文件开发 创建脚手架项目: abc-cli $ mkdir abc-cli && cd abc-cli 全局安装 lerna, $ npm i -g lerna 基于 lerna 完成项目初始化 $ lerna init 基于 lerna 创建脚手架 cli $ lerna create cli一路回车 好现在生成了一个 cli 的模板,目前需要…...

吴恩达《机器学习》学习笔记

本笔记资料来源于 http://www.ai-start.com/ml2014/,该笔记来自于https://blog.csdn.net/dadapongi6/article/details/105668394,看了忘,忘了看,再看一遍。 时间统计:2024.2.29 5个番茄钟,从week1开始&…...

【FPGA】线性反馈移位寄存器(LFSR)的Verilog实现

什么是移位寄存器 移位寄存器:是指多个寄存器并排相连,前一个寄存器的输出作为下一个寄存器的输入,寄存器中存放的数据在每个时钟周期向左或向右移动一位。 下面的右移移位寄存器因为左侧没有有效输入,所以在第4个时钟周期&…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

在rocky linux 9.5上在线安装 docker

前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

蓝桥杯 冶炼金属

原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...