redis的事务不是原子性

Reference: https://blog.csdn.net/u011692780/article/details/81213010

一、事务的四大特性

关系型数据库的事务具有四个特性:

1. 原子性

2. 一致性

3. 隔离性

4. 持久性

二、而在我们redis数据库中,事务回事什么样子的呢?

首先我们给出一个定义:redis的事务中,一次执行多条命令,本质是一组命令的集合,一个事务中所有的命令将被序列化,即按顺序执行而不会被其他命令插入

在redis中,事务的作用就是在一个队列中一次性、顺序性、排他性的执行一系列的命令。

事务的生命周期:

1. 事务的创建:使用MULTI开启一个事务

2. 加入队列:在开启事务的时候,每次操作的命令将会被插入到一个队列中,同时这个命令并不会被真的执行

3. EXEC命令进行提交事务

常用的关于事务的命令有:

1. MULTI:使用该命令,标记一个事务块的开始,通常在执行之后会回复OK,(但不一定真的OK),这个时候用户可以输入多个操作来代替逐条操作,redis会将这些操作放入队列中。

2. EXEC:执行这个事务内的所有命令

3. DISCARD:放弃事务,即该事务内的所有命令都将取消

4. WATCH:监控一个或者多个key,如果这些key在提交事务(EXEC)之前被其他用户修改过,那么事务将执行失败,需要重新获取最新数据重头操作(类似于乐观锁)。

5. UNWATCH:取消WATCH命令对多有key的监控,所有监控锁将会被取消。

注意:关于乐观锁等概念:

乐观锁:就像他的名字,不会认为数据不会出错,他不会为数据上锁,但是为了保证数据的一致性,他会在每条记录的后面添加一个标记(类似于版本号),假设A 获取K1这条标记,得到了k1的版本号是1,并对其进行修改,这个时候B也获取了k1这个数据,当然,B获取的版本号也是1,同样也对k1进行修改,这个时候,如果B先提交了,那么k1的版本号将会改变成2,这个时候,如果A提交数据,他会发现自己的版本号与最新的版本号不一致,这个时候A的提交将不会成功,A的做法是重新获取最新的k1的数据,重复修改数据、提交数据。

悲观锁:这个模式将认定数据一定会出错,所以她的做法是将整张表锁起来,这样会有很强的一致性,但是同时会有极低的并发性(常用语数据库备份工作,类似于表锁)。

那么,现在我们来执行一次具体看看redis的事务机制:

首先我会开启事务,并向数据库中存储4条数据,可以看到没执行一条命令的时候都会显示入队,并不会返回执行结果,说明redis中在事务提交之前,其内部的所有命令将不会被执行:

那么,如果中间有命令出错了会怎样呢?现在我随便打几个字符试一试:

可以看出,在第三条命令中我随便打了几个字符,提交事务的时候并没有成功,这也很符合我们对事务的理解,嗯~具有原子性。但是,有一个细节,那就是错误命令在我输入的时候就已经报错了,也就是说这个条错误命令在进入队列的时候redis就已经知道这是一条错误命令,这样,整个事务的命令将全部失败,那么,有没有一种可能某个错误指令在进入队列的时候redis还没有发现他的错误呢?我们试一试下面这个例子:

问题出现了,我们可以看到,name+1这条指令其实是错误的,但是提交事务的时候会发现,这条错误命令确实没有执行,但是其他正确的命令却执行,这是为什么的?

原因是在redis中,对于一个存在问题的命令,如果在入队的时候就已经出错,整个事务内的命令将都不会被执行(其后续的命令依然可以入队),如果这个错误命令在入队的时候并没有报错,而是在执行的时候出错了,那么redis默认跳过这个命令执行后续命令。也就是说,redis只实现了部分事务。

下面我们来看看刚刚提到的锁的问题,我们说过,redis的锁CAS(check and set)类似于乐观锁,redis的实现原理是使用watch进行监视一个(或多个)数据,如果在事务提交之前数据发生了变化(估计使用了类似于乐观锁的标记),那么整个事务将提交失败,我们可以举一个例子,我们开启两个终端,模拟两个人的操作,设置一条数据为count,初始时100,现在A对其进行监控,并且为count增加20

在没有提交之前,B也获取了这个count,为其减少50,

那么这个时候A如果提交事务,会出现失败提示:

可以看到,在A对数据的修改过程中,B对数据进行了修改,那么这条数据的“标记”就发生了变化,已经不是当初A取出数据的时候的标记了,这样,A的事务也就提交失败了。

最后通过上述的实验,我们总结redis事务的三条性质:

1. 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断
2. 没有隔离级别的概念:队列中的命令在事务没有被提交之前不会被实际执行
3. 不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制

三、Redis中的事务为什么没有原子性与watch锁

Redis事务可以一次执行多个命令,它先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令

在传统的关系型数据中,只要有任意一条指令失败,则整个事务都会被撤销回滚,而在Redis中,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做,也因此得出 Redis 事务的执行并不是原子性的。

multi,代表一段事务的开始

exec,代表一个事务的提交

queued,代表某个指令在队列中

但是,也有例外,比如如下这种情况

discard,代表某个事务撤销

watch 锁 ,在事务中不能改变被锁的值  (exec提交后返回nil)

四、总结

在redis中,对于一个存在问题的命令,如果在入队的时候就已经出错,整个事务内的命令将都不会被执行(其后续的命令依然可以入队),如果这个错误命令在入队的时候并没有报错,而是在执行的时候出错了,那么redis默认跳过这个命令执行后续命令。也就是说,redis只实现了部分事务。

总结redis事务的三条性质:

1. 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断
2. 没有隔离级别的概念:队列中的命令在事务没有被提交之前不会被实际执行
3. 不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制
---------------------
作者:XCCS_澍
来源:CSDN
原文:https://blog.csdn.net/u011692780/article/details/81213010
版权声明:本文为博主原创文章,转载请附上博文链接!

原文地址:https://www.cnblogs.com/skying555/p/10398724.html

时间: 2024-10-18 20:57:50

redis的事务不是原子性的相关文章

Redis 的事务到底是不是原子性的

ACID 中关于原子性的定义: 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节.事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样. 那么 Redis 的事务到底符不符合原子性的特征呢?官方文档对事务的描述如下: 事务可以一次执行多个命令, 并且带有以下两个重要的保证: 事务是一个单独的隔离操作:事务中的所有命令都会序列化.按顺序地执行.事务在执行的过程中,不会被其他客户端发送来的

【redis】-- redis的事务

目录 1.redis事务的执行流程 2.事务开始 3.命令入队 事务队列 4.命令的执行 5.watch命令 6.放弃事务(DISCARD) 7.事务的ACID属性 1.原子性 redis不支持回滚 redis不支持事务回滚的原因: 2.一致性 3.隔离性 4.持久性 Redis通过MULTI.EXEC.WATCH等命令来实现事务( transaction)功能.事务提供了一种将多个命令请求打包,然后- -次性.按顺序地执行多个命令的机制,并且在事务执行期间,服务器不会中断事务而改去执行其他客户

Redis的事务机制

1.redis的事务是什么 可以一次执行多个命令,本质是一组命令的集合,一个事务中的所有命令都会被序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞(排队时后来者插到先到者前面的行为.) 也就是说,在队列中,一次性.顺序性.排他性的执行一系列命令的行为. 看看官方的介绍: 注: redis 的事务是能够使用 MULTI 命令的行为,这个命令通常会响应为 OK,在这种情况下,使用者可以进行多个命令的操作,redis会安排它们入队列而不是执行这些命令,这些所有命令在键入 EXEC 时才会被调用

Redis的事务

Redis对事务的支持是部分支持,不想oracle,要么都成功要么都失败,Redis可以部分成功部分失败 1 是什么: 可以一次执行多个命令,本质是一组命令的集合.一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其他命令插入,不许加塞 2 能干嘛: 一个队列中,一次性.顺序性.排他性的执行一系列命令 3 怎么玩 Redis 事务命令 下标列出了redis事务的相关命令 1. DISCARD 取消事务,放弃执行事务块内的所有命令. 2. EXEC 执行所有事务块内的命令 3. MULTI

第三课作业——set类型、sorted set类型的增删改查,redis的事务

第三课时作业 静哥 by 2016.2.23~2016.3.6   [作业描述] 1.总结什么是set以及什么是sorted set,并完成对set以及sorted set的增删改查(查需要至少4种方式,比如列表,单个节点等) 2.总结redis的事务特征,并且实际操作事务的提交  丢弃以及乐观锁 [作业一:总结什么是set以及什么是sorted set,并完成对set以及sorted set的增删改查] (1) set是字符串的无序集合,集合内的成员可以是重复: sorted set是有序集合

Redis的事务和watch

redis的事务 严格意义来讲,redis的事务和我们理解的传统数据库(如mysql)的事务是不一样的. redis中的事务定义 Redis中的事务(transaction)是一组命令的集合. 事务同命令一样都是Redis的最小执行单位,一个事务中的命令要么都执行,要么都不执行.事务的原理是先将属于一个事务的命令发送给Redis,然后再让Redis依次执行这些命令. Redis保证一个事务中的所有命令要么都执行,要么都不执行.如果在发送EXEC命令前客户端断线了,则Redis会清空事务队列,事务

6.Redis的事务

Redis的事务(Redis部分支持事务) a)是什么 可以一次执行多个命令,本质是一组命令的集合.一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞 b)能干吗 一个(队列)中,一次性.顺序性.排他性的执行一系列命令 c)怎么用 MULTI 开始事务 EXEC 执行事务 DISCARD 取消事务 WATCH 监听一个(或多个)key,如果在事务执行之前 key 被其他命令所改动,那么事务将被打断 UNWATCH 取消WATCH命令对所有key的监视 CASE1:正

【Redis源码剖析】 - Redis之事务的实现原理

原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/article/details/51262268 今天为大家带来Redis中事务部分的源码分析.Redis的事务机制允许将多个命令当做一个独立的单元运行,主要包括multi.exec.watch.unwatch.discard五个相关命令.如果你还不熟悉这几个命令,可以先看看我的另一篇文章[Redis学习笔记(七)] Redis中的事务 本文所讲述的内容主要涉及redis.h和multi.c两个源文件,依据惯例,

Redis的事务功能详解

Redis的事务功能详解 MULTI.EXEC.DISCARD和WATCH命令是Redis事务功能的基础.Redis事务允许在一次单独的步骤中执行一组命令,并且可以保证如下两个重要事项: >Redis会将一个事务中的所有命令序列化,然后按顺序执行.Redis不可能在一个Redis事务的执行过程中插入执行另一个客户端发出的请求.这样便能保证Redis将这些命令作为一个单独的隔离操作执行. > 在一个Redis事务中,Redis要么执行其中的所有命令,要么什么都不执行.因此,Redis事务能够保证