跟我一起学Redis之Redis事务简单了解一下
wptr33 2024-12-22 21:12 77 浏览
前言
关系数据库中的事务,小伙伴们应该是不陌生了,不管是在开发还是在面试过程中,总有两个问题逃不掉:
- 说说事务得特性;
- 事务隔离级别是怎么一回事?
事务处理不好,数据就可能不准确,最终就会导致业务出问题;借此机会简单回顾一下事务特性及其隔离级别,就当是复习了;
事务特性(ACID)
- 原子性(Atomicity) 指事务内所有操作要么一起执行成功,要么都一起失败(或者说是回滚);如事务经典转账案例:A给B转账,A把钱扣了,但B没有收到;可见这种错误是不能接受的,最终会回滚,这也是原子性的重要性。
- 一致性(Consistency) 指事务执行前后的状态一致,如事务经典转账案例:A给B互相转账,不管怎么转,最终两者钱的总和还是不变;
- 持久性(Durability) 指事务一旦提交,数据就已经永久保存了,不能再回滚;
- 隔离性(Isolation) 指多个并发事务之间的操作互不干扰,但是事务的并发可能会导致数据脏读、不可重复读、幻读问题,根据业务情况,采用事务隔离级别进行对应数据读问题处理。
事务隔离级别
- 都未提交(Read uncommitted) 指一个事务读取到其他未提交事务的数据。可能导致数据脏读。 转账案例:A正在给B转账,本来转的1000,A多输入了个0,变成10000,但此事务还未提交,但此时B查询到转入的是10000,但A取消事务回滚之后,B又查询不到转入的数据。这种情况就是脏读
- 都已提交(Read committed) 指一个事务只能读取到其他事务已提交的数据,从而解决了脏读的问题。但可能导致数据不可重复读; 转账案例:A要给B转账1000,A先查看了一下余额,有1000,然后开始给B转钱,但此时A家里电费通过开启的自动缴费功能,自动从A账户扣除200缴纳电费,并提交;当A转账准备提交,再次确认余额时,钱少了200。这样就导致同一个事务中多次查询的结果不一致,这种情况就是不可重复读;
- 可重复读(Repeatable read) 指事务只要一开启,就不允许其他事务进行修改操作,从而解决了不可重复读问题。但可能导致数据幻读; 转账案例:A经常给B转账,到年底了,需要查账,然后开启了一个事务进行查询统计,刚开始查询只是10条转账记录,正准备统计时,因为紧急情况A需要给B转一笔钱应急,从而新增了一条新记录,并提交;而查账事务正在统计中,最后发现转账额和看到的10条转账记录不匹配。这种情况就是幻读
- 序列化(Serializable ) 指事务之间只能串行话执行,就像队列一样,排队进行,这样就解决了幻读的问题,但是这种级别的并发性能不高,非特殊需求,这种级别一般不用。
正文
转入正题,结合关系型数据库的事务来看看Redis中事务有什么不同;
Redis事务是指将多条命令加入队列,一次批量执行多条命令,每条命令会按顺序执行,事务执行过程中不会受客户端传入的命令请求影响。
Redis事务的相关命令如下:
- MULTI:表示一个事务的开启,即开启事务;
- EXEC:执行事务中的所有命令,即提交;
- DISCARD:放弃事务;和回滚不一样,Redis事务不支持回滚。
- WATCH:监视Key改变,用于实现乐观锁。如果监视的Key的值改变,事务最终会执行失败。
- UNWATCH:放弃监视。
Redis事务和关系型数据库的事务不太一样,它不保证原子性,也没有隔离级别的概念。来,结合命令演示,实战说明一切:
没有隔离级别:
如上图所示,当事务开启时,事务期间的命令并没有执行,而是加入队列,只有执行EXEC命令时,事务中的命令才会按照顺序一一执行,从而事务间就不会导致数据脏读、不可重复读、幻读的问题,因此就没有隔离级别。
不保证原子性:
如上图所示,在通过EXEC执行事务时,其中命令执行失败不会影响到其他命令的执行,并没有保证同时成功和同时失败的原子操作,尽管这样,Redis事务中也没有提供回滚的支持,官方提供了两个理由:
大概的意思就是:
- 使用Redis命令语法错误,或是将命令运用在错误的数据类型键上(如对字符串进行加减乘除等),从而导致业务数据有问题,这种情况认为是编程导致的错误,应该在开发过程中解决,避免在生产环境中发生;
- 由于不用支持回滚功能,Redis内部简单化,而且还比较快;
在事务命令入队过程中,发现相关命令逻辑使用错误,可以进行放弃该事务;如果使用错误的Redis命令,且没有放弃事务,最终也会导致事务整体执行失败,这也算是为原子性扳回一局,如下:
放弃事务
命令语法错误导致事务执行失败
使用WATCH实现乐观锁
说到乐观锁,就和悲观锁一起简单说说对其的理解:
乐观锁:就是非常乐观,做什么事都往好处想; 对于数据库操作,就认为每次操作数据的时候都认为别的操作不会修改,所以不会加锁,而是通过一个类似于版本的字段来标识该数据是否修改过,在执行本次操作前先判断是否修改过,如果修改过就放弃本次操作重新再来;
悲观锁:就是非常悲观,做什么事都觉得不好;对于数据库操作,每次操作数据数据都会认为别的操作会修改当前数据,所以都要对其进行加锁,类似于表锁和行锁。
WATCH通过监视指定Redis Key,如果没有改变,就执行成功,如果发现对应值发生改变,事务就会执行失败,如下图;
那会一直监视指定的Key吗?,答案当然是不会的,以下三种方式可以取消监视:
- 事务执行之后,不管是否执行成功还好是失败,都会取消对应的监视;
- 当监视的客户端断开连接时,也会取消监视;
- 可以手动UNWATCH取消所有Key的监视;
Redis事务优缺点
优点:
- 一次性按顺序执行多个Redis命令,不受其他客户端命令请求影响;
- 事务中的命令要么都执行(命令间执行失败互相不影响),要么都不执行(比如中间有命令语法错误);
缺点:
- 事务执行时,不能保证原子性;
- 命令入队每次都需要和服务器进行交互,增加带宽;
注意
- 当事务中命令语法使用错误时,最终会导致事务执行不成功,即事务内所有命令都不执行;
- 当事务中命令知识逻辑错误,就比如给字符串做加减乘除操作时,只能在执行过程中发现错误,这种事务执行中失败的命令不影响其他命令的执行。
总结
对于Redis事务,其实用的不是很多,大部分喜欢使用Lua脚本进行批量命令的执行,同时还能保证命令执行的原子性。
那为什么要说Redis事务呢?
在之前计划写这篇文章的时候,和一些朋友简单沟通过,大家的确用的不多,基本上都是用Lua脚本;但面试会时不时遇到过Redis事务的问题,最常见的是Redis中的事务和关系型数据库中的事务有什么区别,这是从面试角度出发有这篇文章;
其实Redis 2.6版本之前,还不支持Lua脚本时,Redis事务对于批量按序执行命令的场景也是很用的;就拿当下来说,如果一些业务需批量按序执行命令的,同样可以使用,并非一定要Lua脚本。这是从使用角度来说;
最后从学习角度来说,既然学Redis,就应该尽可能地了解的多一点。 下一篇说说持久化。
作者:Code综艺圈
链接:https://juejin.im/post/6894431249759207438
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
相关推荐
- oracle数据导入导出_oracle数据导入导出工具
-
关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...
- 继续学习Python中的while true/break语句
-
上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个else解...
- python continue和break的区别_python中break语句和continue语句的区别
-
python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...
- 简单学Python——关键字6——break和continue
-
Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...
- 2-1,0基础学Python之 break退出循环、 continue继续循环 多重循
-
用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...
- Python 中 break 和 continue 傻傻分不清
-
大家好啊,我是大田。今天分享一下break和continue在代码中的执行效果是什么,进一步区分出二者的区别。一、continue例1:当小明3岁时不打印年龄,其余年龄正常循环打印。可以看...
- python中的流程控制语句:continue、break 和 return使用方法
-
Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...
- L017:continue和break - 教程文案
-
continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...
- 作为前端开发者,你都经历过怎样的面试?
-
已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...
- 面试被问 const 是否不可变?这样回答才显功底
-
作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...
- 2023金九银十必看前端面试题!2w字精品!
-
导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。答案:CSS的盒模型是用于布局和定位元素的概念。它由内容区域...
- 前端面试总结_前端面试题整理
-
记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...
- 由浅入深,66条JavaScript面试知识点(七)
-
作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录由浅入深,66条JavaScript面试知识点(一)由浅入深,66...
- 2024前端面试真题之—VUE篇_前端面试题vue2020及答案
-
添加图片注释,不超过140字(可选)1.vue的生命周期有哪些及每个生命周期做了什么?beforeCreate是newVue()之后触发的第一个钩子,在当前阶段data、methods、com...
- 今年最常见的前端面试题,你会做几道?
-
在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...
- 一周热门
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)
