在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. 第八天py

    我发现这个老师讲的太基础只是我懒得跳过而已想慢慢听 列表公共功能 索引 切片 for 长度 特有功能 翻转 排序 追加 插入 索引位置 删除

  2. maven 配置mirror后,本地库与远端库冲突

    settings.xml中主要包括以下元素: localRepository interavtiveMode offline pluginGroups proxies servers mirrors ...

  3. Maven Web项目部署到Tomcat下问题

    但是也遇到了很多问题,下面记录一下Web项目部署到Tomcat下的问题 1.普通的WEB项目,就是虽然是用maven搭建的,但是没有使用profiles.xml文件来配置参数.这样的项目可以通过以下的 ...

  4. 怎么关闭win10防火墙

    reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender" /v "Disable ...

  5. 更新快排中的partition

    这一次是将partition 过程中, 维护三个区域. <x   =x  >x  三区域. 还有个待定的区域. /* * 将数组划分为三个分区, 小于arr[R], 等于arr[R], 大 ...

  6. nowcoder 211E - 位运算?位运算! - [二进制线段树][与或线段树]

    题目链接:https://www.nowcoder.com/acm/contest/211/E 题目描述 请实现一个数据结构支持以下操作:区间循环左右移,区间与,区间或,区间求和. 输入描述: 第一行 ...

  7. [No0000155]为什么32位机器最大只能用到4GB内存

    在此之前先来了解一些计算机存储单位之间的关系以及计算机系统结构和PC硬件方面的一些知识. 一.计算机存储单位之间的关系 ,最小的存储单位. 个二进制位为一个字节(B),即1B = 8bit,最常用的单 ...

  8. [cloud][sdn] neutron了解

    了解 neutron 文档:https://yeasy.gitbooks.io/openstack_understand_neutron/content/ LB讲的不细.DVR讲的不清晰. 读了全文之 ...

  9. [administrative][qemu][kvm] qemu使用--bridge-helper

    公司服务器,源码安装的 qemu-2.9.0. 不是yum装的. 问题1:非超级用户的kvm权限问题: 略,直接超级用户使用. 也许有用? https://access.redhat.com/docu ...

  10. js实现数字千分位

    /** * * @param num * @param precision * @param separator * @returns {*} *=========================== ...