在Redis中,事务是以multi/exec/discard进行的, 其中multi表示事务的开始, exec表示事务的执行,discard表示丢弃事务。

 127.0.0.1:> multi     # 事务的开始
OK
127.0.0.1:> set 1 # 添加命令
QUEUED
127.0.0.1:> set 2
QUEUED
127.0.0.1:> exec # 执行事务
) OK
) OK
127.0.0.1:> get
""
127.0.0.1:> get
""
127.0.0.1:>
 127.0.0.1:> multi     # 事务的开始
OK
127.0.0.1:> set 3 # 添加命令
QUEUED
127.0.0.1:> set
QUEUED
127.0.0.1:> discard #丢弃事务
OK
127.0.0.1:> exec # 此时在执行exec命令会报错。
(error) ERR EXEC without MULTI
127.0.0.1:>

上面演示了一个完整的事务过程,所有的指令在 exec 之前不执行,而是缓存在服务器的一个事务队列中,服务器一旦收到 exec 指令,才开执行整个事务队列,执行完毕后一次性返回所有指令的运行结果。因为 Redis 的单线程特性,它不用担心自己在执行队列的时候被其它指令打断,可以保证他们能得到的“原子性”执行。另外QUEUED没什么特别的意味,就像OK一样,他只是申明命令已经放入缓存队列中了。

redis原子性?


  在mysql中事务会有一个原子执行,如果在事务中一个命令执行时发生错误,其他命令也不会得到执行,但是在redis中是否存在这样的设置? 

 127.0.0.1:> multi          # 事务的开始
OK
127.0.0.1:> set 's'
QUEUED
127.0.0.1:> INCR
QUEUED
127.0.0.1:> set 'ss'
QUEUED
127.0.0.1:> exec
) OK
) (error) ERR value is not an integer or out of range # 因为键为1的值为字符串,不能对其自增,因此报错。
) OK
127.0.0.1:> mget 2 # 键值对2 ‘ss'还是设置成功。
) "s"
) "ss"

从上面我们可以看出,即使在Redis事务中存在错误的命令,也不会妨碍后面的命令执行。

redis中管道


  在上面 Redis 事务例子中,在发送每个指令到事务缓存队列时都要经过一次网络读写,当一个事务内部的指令较多时,需要的网络 IO 时间也会线性增长。所以通常 Redis 的客户端在执行事务时都会结合 pipeline 一起使用,这样可以将多次 IO 操作压缩为单次 IO 操作。来增加性能。 

   import redis

   re = redis.Redis('localhost', , db =)

   p = re.pipeline(transaction=True)
p.multi()
p.set('test_1', 'test——1')
p.set('test_2', 'test_2')
p.execute() # redis 客户端中查询结构
127.0.0.1:> get test_1
"test\xe2\x80\x94\xe2\x80\x941"
127.0.0.1:> get test_2
"test_2"
127.0.0.1:>

 watch命令


  假如有多个客户端会并发进行操作。我们可以通过 Redis 的分布式锁来避免冲突,这是一个很好的解决方案。但是分布式锁是一种悲观锁,那是不是可以使用乐观锁的方式来解决冲突呢?

  有这样一种情况,假如多个用户进行并发操作时,需要将值取出然后操作再回写到对应键的值上,这可能会导致最终的值不是正确的值。这里一种解决办法是分布式锁(悲观所),另一种就是Watch(乐观锁)。

  watch命令会在事务开始之前看住 1 个或多个指定变量,当服务器收到了 exec 指令要顺序执行缓存的事务队列时,Redis 会检查关键变量自 watch 之后,是否被修改了 (包括当前事务所在的客户端)。如果关键变量被人动过了,exec 指令就会返回 null 回复告知客户端事务执行失败,这个时候客户端一般会选择重试。(watch必须再事务之前执行,不能再事务中执行)

   127.0.0.1:> set 'test'
OK
127.0.0.1:> watch test
OK
127.0.0.1:> INCR test # watch之后改变test的值
(integer)
127.0.0.1:> multi # 开始事务
OK
127.0.0.1:> INCR test # 改变test的值
QUEUED
127.0.0.1:> exec # 执行事务
(nil) # 返回空值,事务执行失败。 127.0.0.1:> set 'test_2' # 设置test-
OK
127.0.0.1:> watch test_2 # 监听test_2
OK
127.0.0.1:> multi
OK
127.0.0.1:> INCR test_2 #修改test_2的值
QUEUED
127.0.0.1:> exec # 执行成功
) (integer)

  在py客户端中对于一个值的修改我们可以采用这样形式

 import redis

 def modify_test(client, key):
while True:
client.watch(key)
value = int(client.get(key))
value += # 修改值
pipe = client.pipeline(transaction=True)
pipe.multi()
pipe.set(key, value)
try:
pipe.execute()
break # 修改成功
except redis.WatchError:
continue # 值已经被修改,执行失败
return int(client.get(key)) # 重新获取值 client = redis.StrictRedis()
key = "test"
client.setnx(key, ) # setnx 做初始化
print (modify_test(client, key))

【Redis】事务的更多相关文章

  1. Redis学习笔记~Redis事务机制与Lind.DDD.Repositories.Redis事务机制的实现

    回到目录 Redis本身支持事务,这就是SQL数据库有Transaction一样,而Redis的驱动也支持事务,这在ServiceStack.Redis就有所体现,它也是目前最受业界认可的Redis ...

  2. Redis学习笔记(4) Redis事务、生存时间及排序

    1. Redis事务 Redis中的事务(transaction)是一组命令的集合,一个事务中的命令要么都执行,要么都不执行.事务的原理是先将属于一个事务的命令发送给Redis,然后再让Redis依次 ...

  3. REDIS 事务机制

    基本事务操作: 任何数据库都必须要保证一种原子执行操作:最基本的原子执行操作肯定是需要提供: 举一个例子来说明: 当对某个Key 做一个统计: 可能不同的Client做它那部分的统计,一段时间后,服务 ...

  4. redis 事务

    概述 相信学过MySQL等其他数据库的同学对事务这个词都不陌生,事务表示的是一组动作,这组动作要么全部执行,要么全部不执行.为什么会有这样的需求呢?看看下面的场景: 微博是一个弱关系型社交网络,用户之 ...

  5. (6)redis 事务

    redis对事务的支持目前还比较简单.redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令. 由于redis是单线程来处理所有client的请求的所 ...

  6. Redis事务的分析及改进

    Redis事务的分析及改进 Redis的事务特性 数据ACID特性满足了几条? 为了保持简单,redis事务保证了其中的一致性和隔离性: 不满足原子性和持久性: 原子性 redis事务在执行的中途遇到 ...

  7. Spring Framework 中启动 Redis 事务操作

    背景: 项目中遇到有一系列对Redis的操作,并需要保持事务处理. 环境: Spring version 4.1.8.RELEASE Redis Server 2.6.12 (64位) spring- ...

  8. 2016022612 - redis事务命令集合

    参考地址:http://www.yiibai.com/redis/redis_transactions.html Redis事务由指令 MULTI 启动,以EXEC结束. 1.multi 用途:事务开 ...

  9. 2016022606 - redis事务

    Redis事务 Redis事务让一组命令在单个步骤执行.事务中有两个属性,说明如下: 1.在一个事务中的所有命令按顺序执行作为单个隔离操作.通过另一个客户端发出的请求在Redis的事务的过程中执行,这 ...

  10. Redis事务和分布式锁

    Redis事务 Redis中的事务(transaction)是一组命令的集合.事务同命令一样都是Redis最小的执行单位,一个事务中的命令要么都执行,要么都不执行.Redis事务的实现需要用到 MUL ...

随机推荐

  1. 一、在windows环境下修改pip镜像源的方法(以python3为例)

    在windows环境下修改pip镜像源的方法(以python3为例) 1.在windows文件管理器中,输入 %APPDATA% 2.会定位到一个新的目录下,在该目录下新建pip文件夹,然后到pip文 ...

  2. 【TOP100案例专访】当当网工程师林嘉琦谈双11大促经验及APM实践

    导读:第七届TOP100全球软件案例研究峰会将于11月30日-12月3日在北京国家会议中心举办,本届峰会以“释放AI生产力 让组织向智能化演进”为开幕式主题,旨在推动企业在趋势下拥抱AI.探索和思考A ...

  3. python中的os

    import sys, os print(__file__) # 绝对路径,实际是文件名 /Users/majianyu/Desktop/test/bin/bin.py print(os.path.a ...

  4. HDU 2072 - 单词数 - [(有点小坑的)字典树模板题]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2072 Problem Descriptionlily的好朋友xiaoou333最近很空,他想了一件没有 ...

  5. [No000011A]Office Excel设置显示日期与星期

    设置excel日期格式,自定义,yyyy-mm-dd 上午/下午 hh:mm:ss AM/PM dddd aaaa

  6. java 验证字符串是否包含中文字符

    中文的模式:"[\\u4e00-\\u9fa5]|\\\\u" 例子: private static final Pattern p = Pattern.compile(" ...

  7. phpstorm之ssh链接远程Linux服务器

    save ssh session inPHPstorm. open PHPstorm,open File,> Settings >search for 'Deployment' > ...

  8. [administrative] windows 下制作USB启动盘的工具

    arch魔教的文档:  https://wiki.archlinux.org/index.php/USB_flash_installation_media windows 下的 dd: https:/ ...

  9. 图->定义

     文字描述 顶点 指图中的数据元素 弧尾 若<v,w>属于两个顶点之间的关系的集合,表示从v到w的一条弧,则v为弧尾或初始点 弧头 若<v,w>属于两个顶点之间的关系的集合,表 ...

  10. 《HTTP - 基于http的认证》

    推荐一首歌 - 好吧,今天刚入职第二天,也没听歌. 哈哈哈哈. 1:何为认证? - 其实这个问题就比较宽泛了,总的来说,就是你有证明你身份的标识. - 和人类社会一样,你花了钱想看一场场演唱会,但是谁 ...