Redis(二十)-Redis的事务和锁机制

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 何为事务呢?我的理解是事务是一种机制,是一个不可分割的工作单元,要么都执行,要么都不执行。

事务

何为事务呢?我的理解是事务是一种机制,是一个不可分割的工作单元,要么都执行,要么都不执行。其具有如下四个特性:

1.原子性(Atomicity)

原子性是指事务是一个不可分割的工作单元,事务中的操作要么都发生,要么都不发生。

2.一致性(Consistency)

一致性是指事务前后数据的完整性必须保持一致。

3.隔离性(Isolation)

隔离性是指多个事务并发执行时,一个事务的执行不应影响其他事务的执行,也就是说事务之间是相互隔离的。

4.持久性(Durability)

持久性是指一个事务一旦被提交,它对数据库中的数据的改变是持久的,接下来即使数据库发生故障也不应该对其有任何影响。在关系型数据库中,事务执行完之后,执行结果就写到了硬盘中。

上面就是事务的四个特性,简称ACID。关系型数据库事务都满足这四个特性。

Redis的事务下面就是一个Redis事务的使用示例。

 

Redis事务的简介

Redis事务其实就是将多个命令包裹起来,一次性执行。默认是不开启事务的。Redis事务从开始到执行会经历如下三个阶段:

1.开始事务MULTI

我们通过MULTI命令将执行该命令的客户端从非事务状态切换至事务状态,通过在客户端状态的flags属性中打开REDIS_MULIT标识来完成的。

127.0.0.1:6379> MULTI
OK

2.命令入队

如果客户端正处于事务状态时,当添加新命令时,首先会判断这个命令是否是EXEC,DISCARD,WATCH或者MULTI这四个命令, 如果不是的话则会把命令放入事务队列中,每个Redis客户端都有自己的事务队列,它是一个multlCmd类型的数组,数组中的每个multlCmd类型的数组,数组中的每个multiCmd结构都保存了一个已入队命令的相关信息,包括指向命令实现函数的指针,命令的参数,以及参数的数量,它以先进先出(FIFO)的方式保存入队的命令,较先入队的命令会被放到数组前面,而较后入队的命令会被放在数组的后面。

127.0.0.1:6379> set name zhangsan
QUEUED

3.执行事务EXEC

当一个处于事务状态的客户端向服务器发送EXEC命令时,这个EXEC命令将立即被服务器执行。服务器会遍历这个客户端的事务队列,执行队列中保存的所有命令,最后将执行命令所得的结果全部返回给客户端。

127.0.0.1:6379> exec
1) OK
2) "zhangsan"
3) OK

Redis事务的过程

在Redis事务中通过MULTI命令开启事务,输入的命令会依次进入命令队列中,此时命令并不会被执行,它相当于MySQL的事务中的Begin命令。通过exec命令执行事务,进入执行阶段,这个阶段会依次执行命令队列中的每个命令,它相当于MySQL的事务中的Commit命令。通过discard命令来放弃命令的组队,它相当于MySQL的事务中的Rollback命令。

1d0e2169c3cf6dfad16f9a1a242a7a6a_ec85a88aaacb4b6487c251dabc1cc2b8.png

事务的错误处理

如果在组队过程中某个命令报告错误,执行时整个的所有队列都会被取消。

669f2cf7c86e3395cd76dc06456b1dec_b8492a9c4c2942d3865c94236dd89f55.png

演示一下:

126461ebd373677f92213f0effe586c5_89cba990f94a4abf80e32a01f6446f43.png

如果是在执行阶段,某个命令发生了错误,那么只会影响该命令的执行,而不会影响其他命令的执行。

1ea28745cc9b359c37645f1759551d38_4ef61c08667247069c92cd80ffaa7cd8.png

演示一下:

ef2a4a66a55ab94f9e926e5866d54542_62c6a308ba5a4711bc990d42547b8978.png

Redis事务的相关特性

Redis事务并不完全具有ACID这四种特性,它只具有一致性和隔离性。原因如下:

1.Redis使用单线程的方式来执行事务(以及事务队列中的命令),并且服务器保证,在执行事务期间不会中断事务,因此,Redis中的事务总是以串行的方式执行,并且事务是具有隔离性的。

2.Redis事务不过是一组包裹起来的命令,Redis并没有做特殊的持久化工作,所以一般而言Redis事务不具有持久性,Redis的持久性策略可以看上一篇文章。

3.Redis不支持事务回滚机制(rollback),即使事务队列中的某个命令在执行期间出现了错误,整个事务也会继续执行下去,直到将事务队列中的所有命令都执行完毕为止,所以,Redis事务不支持原子性。如下图所示:

90c7acf166a429a3f37becbb0413864a_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ1MzQ4MDg=,size_16,color_FFFFFF,t_70#pic_center.png

4.事务总是具有一致性的。即事务执行前后数据是一致的。

Redis事务的实现原理

Redis实现事务,是基于COMMANDS队列的,也就是说,如果没有开启事务,command将会被立即执行并返回执行结果,并且直接保存在内存中,如果事务开启,command不会被立即执行,而是排入队列并返回排队状态(具体依赖于客户端(例如:spring-data-redis)自身实现),调用EXEC才会执行COMMANDS队列。

WATCH命令

WATCH命令是一个乐观锁,它可以在EXEC命令执行之前,监视任意数量的数据库键,并在EXEC命令执行时,检查被监视的键是否至少有一个已经被修改过了,如果是的话,服务器将拒绝执行事务,并向客户端返回代表事务执行失败的空回复。如下所示:


与MySQL事务的区别


1.事务的命令不同

MySQL事务的使用如下:

BEGIN : 显式地开启一个事务
COMMIT: 提交事务
ROLLBACK: 结束用户的事务,并撤销正在进行的所有未提交的修改

而Redis事务的使用如下:

MULTI: 标记事务的开始
EXEC: 执行事务的commands 队列
DISCARD: 结束事务,并清除commands队列;

2.默认状态不同

MySQL会默认开启一个事务,且缺省设置是自动提交,即每成功执行一个SQL,一个事务就会马上COMMIT,所以不能Rollback。当然,我们在同一个事务中执行多个SQL时,如果某个SQL执行失败了,则这个事务就会回滚掉。

Redis默认不会开启事务,即command会立即执行,而不会排队,并且不支持Rollback。

3.实现原理不同

MySQL实现事务,是基于UNDO/REDO日志,UNDO日志记录修改前状态,ROLLBACK命令是基于UNDO日志实现的。

REDO记录修改后的状态,COMMIT命令是基于REDO日志实现的。

在MySQL中无论是否开启日志,SQL都会立即执行并返回结果,只是事务开启后执行后的状态记录在REDO日志,执行COMMIT之后,数据才会被写入磁盘。

参考

《Redis设计与实现》

总结

本文简单介绍了Redis事务并将其与MySQL事务做了一下对比。Redis事务只有一致性和隔离性两种特性,不支持原子性和持久性。其实现原理是基于COMMANDS队列的,开启事务之后,命令不会被立即执行,而是排入队列并返回排队状态。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
24天前
|
缓存 NoSQL Redis
Redis 事务
10月更文挑战第18天
24 1
|
1月前
|
监控 NoSQL 算法
Redis主从切换,锁失效怎么办?
在分布式系统中,Redis因其高性能和易用性而被广泛应用于缓存、分布式锁等场景。然而,当Redis采用主从架构以实现高可用性和数据冗余时,主从切换可能带来的锁失效问题成为了一个不容忽视的挑战。本文将深入探讨Redis主从切换导致锁失效的原因、影响及解决方案,旨在为大家提供实用的技术干货。
93 5
|
3月前
|
负载均衡 NoSQL 算法
一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)
这篇文章是关于Java面试中Redis相关问题的笔记,包括Redis事务实现、集群方案、主从复制原理、CAP和BASE理论以及负载均衡算法和类型。
一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)
|
1月前
|
存储 缓存 NoSQL
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
37 2
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
|
1月前
|
NoSQL Java API
美团面试:Redis锁如何续期?Redis锁超时,任务没完怎么办?
在40岁老架构师尼恩的读者交流群中,近期有小伙伴在面试一线互联网企业时遇到了关于Redis分布式锁过期及自动续期的问题。尼恩对此进行了系统化的梳理,介绍了两种核心解决方案:一是通过增加版本号实现乐观锁,二是利用watch dog自动续期机制。后者通过后台线程定期检查锁的状态并在必要时延长锁的过期时间,确保锁不会因超时而意外释放。尼恩还分享了详细的代码实现和原理分析,帮助读者深入理解并掌握这些技术点,以便在面试中自信应对相关问题。更多技术细节和面试准备资料可在尼恩的技术文章和《尼恩Java面试宝典》中获取。
美团面试:Redis锁如何续期?Redis锁超时,任务没完怎么办?
|
1月前
|
设计模式 NoSQL 网络协议
大数据-48 Redis 通信协议原理RESP 事件处理机制原理 文件事件 时间事件 Reactor多路复用
大数据-48 Redis 通信协议原理RESP 事件处理机制原理 文件事件 时间事件 Reactor多路复用
36 2
|
1月前
|
SQL 分布式计算 NoSQL
大数据-42 Redis 功能扩展 发布/订阅模式 事务相关的内容 Redis弱事务
大数据-42 Redis 功能扩展 发布/订阅模式 事务相关的内容 Redis弱事务
24 2
|
1月前
|
NoSQL 关系型数据库 MySQL
Redis 事务特性、原理、具体命令操作全方位诠释 —— 零基础可学习
本文全面阐述了Redis事务的特性、原理、具体命令操作,指出Redis事务具有原子性但不保证一致性、持久性和隔离性,并解释了Redis事务的适用场景和WATCH命令的乐观锁机制。
201 0
Redis 事务特性、原理、具体命令操作全方位诠释 —— 零基础可学习
|
3月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
这篇文章介绍了如何在SpringBoot项目中整合Redis,并探讨了缓存穿透、缓存雪崩和缓存击穿的问题以及解决方法。文章还提供了解决缓存击穿问题的加锁示例代码,包括存在问题和问题解决后的版本,并指出了本地锁在分布式情况下的局限性,引出了分布式锁的概念。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
|
3月前
|
NoSQL 关系型数据库 Redis
Redis6入门到实战------ 九、10. Redis_事务_锁机制_秒杀
这篇文章深入探讨了Redis事务的概念、命令使用、错误处理机制以及乐观锁和悲观锁的应用,并通过WATCH/UNWATCH命令展示了事务中的锁机制。
Redis6入门到实战------ 九、10. Redis_事务_锁机制_秒杀