一文了解:Redis事务
Redis事务
事务提供了一种"将多个命令打包,一次性提交并按顺序执行"的机制,提交后在事务执行中不会中断。只有在执行完所有命令后才会继续执行来自其他客户的消息。
Redis中的使用
Redis通过multi,exec,discard,watch实现事务功能。
- multi:开始事务
- exec:提交事务并执行
- discard:取消事务
- watch:事务开始之前监视任意数量的键
> multi
OK
> set bookName "Redis"
QUEUED
> get bookName
QUEUED
> sadd tag "Redis" "New Book"
QUEUED
> smembers tag
QUEUED
> exec
1) OK
2) "Redis"
3) (integer) 2
4) 1) "Redis"
2) "New Book"
开始事务
> multi
OK
这个命令将Redis_multi选项打开,让客户端从非事务状态变为事务状态

命令入队
> set bookName "Redis"
QUEUED
> get bookName
QUEUED
> sadd tag "Redis" "New Book"
QUEUED
> smembers tag
QUEUED
在事务状态中,Redis命令并不是立即执行的,而是进入一个先进先出的事务队列。QUEUED表示这个命令已经入了事务队列。
执行事务
> exec
1) OK
2) "Redis"
3) (integer) 2
4) 1) "Redis"
2) "New Book"
当执行exec命令时,Redis根据客户端所保存的事务队列, 以先进先出的方式执行事务队列中的命令: 最先入队的命令最先执行, 而最后入队的命令最后执行。
当exec命令执行完毕时,Redis会将结果保存到一个回复队列,并将回复队列返回给客户端。客户端从事务状态退出,一个事务执行完毕。
discard命令
> multi
OK
> set author "lisi"
QUEUED
> discard
OK
> get author
(nil)
discard取消一个事务的命令,表示这个事务被取消。客户端从事务状态退出,回到非事务状态,Redis_multi选项关闭。

watch命令
# Redis客户端1
> watch letter
OK
> multi
OK
> set letter a
QUEUED
> exec
(nil)
# Redis客户端2
> set letter b
OK
# Redis客户端1
> get letter
"b"
设置监控letter键,客户端1进入事务,设置letter的value为a,未提交事务。客户端2设置letter的value为b。回到客户端1提交事务返回的结果为nil,调用get命令得到letter为b。这说明当letter键在其他客户端改变后,事务被取消了,不会被执行,返回失败。
watch命令在事务开始之前监视任意数量的键:当调用exce命令执行事务时,如果任意一个被监视的键已经被其他客户端修改了,那么整个事务不再执行,直接返回失败。

事务异常
命令错误
> set letter ac
QUEUED
> get letter ac
(error) ERR wrong number of arguments for 'get' command
> exec
(error) EXECABORT Transaction discarded because of previous errors.
事务中命令异常属于语法错误,将导致事务无法执行。
运行时异常
> multi
OK
> lpush books "Redis"
QUEUED
> incr books
QUEUED
> lpush books "Python"
QUEUED
> lrange books 0 -1
QUEUED
> exec
1) (integer) 1
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) (integer) 2
4) 1) "Python"
2) "Redis"
上面的例子是事务执行到中间遇到失败了,因为不能对一个字符串进行incr命令,事务在遇到命令执行失败后,后续的命令还继续执行,所以books的值能继续得到设置。这种异常只有程序员在代码中避免。
事务的ACID
原子性
原子意味着要么一起成功执行,要么一起失败回滚。Redis提供的所有API都是原子操作。那么Redis事务只要保证在一批操作中保证原子性,但是在运行时异常中,在一个事务中一个命令出现异常,其他命令还是会继续执行,事务没有回滚机制,所以Redis事务是不保证原子性的。
一致性
事务异常
如果命令错误事务无法执行,如果是运行时异常,Redis会将错误包含在返回结果中,并不影响后续执行,所以事务是一致性的。
Redis进程被终结
在纯内存模式下,Redis没有做持久化,重启之后数据库是空白的,所以是事务一致性的。
在RDB模式下,事务并不会在中途执行保存RDB文件的工作,只有在事务执行完后,RDB工作才可能会开始。所以在事务执行过程中Redis进程被杀死,不管成功多少都不会保存到RDB文件中,所以是一致性的。
在AOF模式下,事务部分语句被写入AOF文件并保存成功,不完整的事务被保存到了AOF文件,当重启Redis时,检查AOF文件不完整,Redis退出并报错。需要把这段不完整的事务删除后才能重启成功,所以是一致性的。
在AOF模式下,事务并未被写入AOF文件,所以重启后Redis数据库是最近一次成功保存到AOF文件中的数据。并没有这次事务的数据,所以是以一致性的。
隔离性
Redis 是单进程程序,并且它保证在执行事务时,不会对事务进行中断,事务可以运行直到执行完所有事务队列中的命令为止。所以事务是带有隔离性的。
持久性
在纯内存模式下,事务肯定不是持续性的。
在RDB模式下,服务器可能在事务执行之后、RDB文件更新之前的这段时间失败,所以 RDB模式下的事务也是不持久的。
在AOF模式下,将命令添加到AOF文件中,但是对文件进行写入并不会马上写到磁盘上,而是先存储到缓冲区。所以数据保存到磁盘上有一段非常小的时间间隔。这种模式下事务也不是持久的。
结语
本人深知水平有限,欢迎指正本文错误之处。
参考资料
《Redis 设计与实现》
《Redis 开发与运维》
《Redis 深度历险:核心原理与应用实践》
欢迎关注公众号:bate喵
专注于Java相关技术:Linux、JVM、SpringCloud、SpringBoot、Docker、Redis、Netty、微服务、高并发等领域,偶尔聊聊学习之道、自控力等方法,致力于成就更好的自己,欢迎大家关注交流,共同成长
一文了解:Redis事务的更多相关文章
- Redis事务原理分析
Redis事务原理分析 基本应用 在Redis的事务里面,采用的是乐观锁,主要是为了提高性能,减少客户端的等待.由几个命令构成:WATCH, UNWATCH, MULTI, EXEC, DISCARD ...
- 探索Redis设计与实现14:Redis事务浅析与ACID特性介绍
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
- Redis事务实现原理
一:简介 Redis事务通常会使用MULTI,EXEC,WATCH等命令来完成,redis实现事务实现的机制与常见的关系型数据库有很大的却别,比如redis的事务不支持回滚,事务执行时会阻塞其它客户端 ...
- Redis 事务支持 ACID 么?
腾讯面试官:「数据库事务机制了解么?」 「内心独白:小意思,不就 ACID 嘛,转眼一想,我面试的可是技术专家,不会这么简单的问题吧」 程许远:「balabala-- 极其自信且从容淡定的说了一通.」 ...
- Redis学习笔记~Redis事务机制与Lind.DDD.Repositories.Redis事务机制的实现
回到目录 Redis本身支持事务,这就是SQL数据库有Transaction一样,而Redis的驱动也支持事务,这在ServiceStack.Redis就有所体现,它也是目前最受业界认可的Redis ...
- Redis学习笔记(4) Redis事务、生存时间及排序
1. Redis事务 Redis中的事务(transaction)是一组命令的集合,一个事务中的命令要么都执行,要么都不执行.事务的原理是先将属于一个事务的命令发送给Redis,然后再让Redis依次 ...
- REDIS 事务机制
基本事务操作: 任何数据库都必须要保证一种原子执行操作:最基本的原子执行操作肯定是需要提供: 举一个例子来说明: 当对某个Key 做一个统计: 可能不同的Client做它那部分的统计,一段时间后,服务 ...
- redis 事务
概述 相信学过MySQL等其他数据库的同学对事务这个词都不陌生,事务表示的是一组动作,这组动作要么全部执行,要么全部不执行.为什么会有这样的需求呢?看看下面的场景: 微博是一个弱关系型社交网络,用户之 ...
- (6)redis 事务
redis对事务的支持目前还比较简单.redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令. 由于redis是单线程来处理所有client的请求的所 ...
随机推荐
- docker 获取镜像
之前提到过,Docker Hub 上有大量的高质量的镜像可以用,这里我们就说一下怎么获取这些镜像. 从 Docker 镜像仓库获取镜像的命令是 docker pull.其命令格式为: docker p ...
- 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数 例如给定nums = [2,7,11,15],target = 9
python解决方案 nums = [1,2,3,4,5,6] #假如这是给定的数组 target = 9 #假如这是给定的目标值 num_list = [] #用来装结果的容器 def run(nu ...
- MySQL之基础操作
一.安装 Mysql是最流行的关系型数据库管理系统之一,由瑞典MySQL AB公司开发,目前属于Oracle公司. MySQL是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数 ...
- volatile的内存语义与应用
volatile的内存语义 volatile的特性 理解volatile特性的一个好方法是把对volatile变量的单个读/写,堪称是使用同一个锁对这些单个读/写操作做了同步. 锁的happens-b ...
- 计算机以及Python的初始
电脑的介绍 CPU:中央处理器,相当于人类的大脑 内存:暂时储存数据,速度快,造价高,断电后丢失 硬盘:长期储存数据.速度相对慢,造价相对低 操作系统:一个软件,连接计算机硬件和系统中的软件. Pyt ...
- 深入学习Spring框架(一)- 入门
1.Spring是什么? Spring是一个JavaEE轻量级的一站式开发框架. JavaEE: 就是用于开发B/S的程序.(企业级) 轻量级:使用最少代码启动框架,然后根据你的需求选择,选择你喜欢的 ...
- js动态生成数据的抓取
需求:爬取https://www.xuexi.cn/f997e76a890b0e5a053c57b19f468436/018d244441062d8916dd472a4c6a0a0b.html页面中的 ...
- TCP/IP协议、三次握手、四次挥手
1.什么是TCP/IP协议 TCP/IP 是一类协议系统,它是用于网络通信的一套协议集合. 传统上来说 TCP/IP 被认为是一个四层协议 1) 网络接口层: 主要是指物理层次的一些接口,比如电缆等. ...
- TCP UDP (转)
互连网早期的时候,主机间的互连使用的是NCP协议.这种协议本身有很多缺陷,如:不能互连不同的主机,不能互连不同的操作系统,没有纠错功能.为了改善这种缺点,大牛弄出了TCP/IP协议.现在几乎所有的操作 ...
- 爬虫之抓js教程
在初学的爬虫过程中,很多人还不知道有些字段是如何生成的,怎样模拟生成这些字段来拼接头部.为了再次纪念[宏彦获水]成语初次面世,特地用[百度登陆]写下一篇登陆百度的教程,以供大家参考. 前面学习了如何在 ...