Redis 的事务机制和管道技术Pipelining


Redis 的事务机制和管道技术Pipelining


事务的四大特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability) 事务的属性:传播行为、隔离级别、只读和事务超时 个人见解:这里小僧认为事务的特性和属性不是一个定西,特性侧重于说明特点,二属性则侧重于说明本身就有的东西,这里举个例子人有鼻子 腿 眼睛 耳朵 这是属性只要是正常人都有这些东西,但是这个人长得帅 骚气 这属于特性,有特点。 关于事务的一些特性和属性的一些具体解释小僧这里就不重复复述了,不懂的自行百度即可。 Redis的事务属性主要通过5个命令来操作的,分别是 multi、exec、watch、unwatch、discard。下面分别介绍下这屋命令的意思: watch key1 key2 ... : 监视一或多个key,如果在事务执行之前,被监视的key被其他命令改动,则事务被打断 ( 类似乐观锁 )

  multi : 标记一个事务块的开始( queued )

  exec : 执行所有事务块的命令 ( 一旦执行exec后,之前加的监控锁都会被取消掉 ) 

  discard : 取消事务,放弃事务块中的所有命令

  unwatch : 取消watch对所有key的监控 下面用多种案例实际操作下: (1)正常执行的情况下,multi开启事务 然后输入一个或者多个命令这是所有命名没有执行,当执行exec操作后是开始执行

Redis 的事务机制和管道技术Pipelining

(2)放弃事务,multi开启事务 然后输入一个或者多个命令这是所有命名没有执行,当执行discard操作后怎放弃执行,不作任何操作,在上一步中把name 的值设置为了ergou,所以get的时候获得ergou

Redis 的事务机制和管道技术Pipelining

(3)若在事务队列中存在命令性错误(类似于java编译性错误),则执行EXEC命令时,所有命令都不会执行

Redis 的事务机制和管道技术Pipelining

(4)若在事务队列中存在语法性错误(类似于java的1/0的运行时异常),则执行EXEC命令时,其他正确命令会被执行,错误命令抛出异常。

Redis 的事务机制和管道技术Pipelining

(5)使用watch检测余额balance,事务期间balance数据未变动,事务执行成功

Redis 的事务机制和管道技术Pipelining

(6)使用watch检测balance,在开启事务后(一窗口),在2窗口执行的操作,更改balance的值,模拟其他客户端在事务执行期间更改watch监控的数据,然后再执行一窗口后命令,执行EXEC后,事务未成功执行。

Redis 的事务机制和管道技术Pipelining

Redis 的事务机制和管道技术Pipelining

一但执行 EXEC 开启事务的执行后,无论事务使用执行成功, WARCH 对变量的监控都将被取消。故当事务执行失败后,需重新执行WATCH命令对变量进行监控,并开启新的事务进行操作。WARCH 指令类似于乐观锁(你有没有想到java的CAS呢?),在事务提交时,如果watch监控的多个KEY中任何KEY的值已经被其他客户端更改,则使用EXEC执行事务时,事务队列将不会被执行,同时返回Nullmulti-bulk应答以通知调用者事务执行失败。 这里你应该问Redis为什么不支持回滚操作呢? 解答:在正常编程中上面案例(3)几乎是不可能出现的,不过案例(4)怎有可能出现,但是Redis作者认为既然使用Redis他会默认你的操作都是正确的,为了保证高性能就不支持回滚操作了。

  • 管道Pipelining Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这意味着通常情况下一个请求会遵循以下步骤: 客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。 服务端处理命令,并将结果返回给客户端。 redis客户端执行一条命令分4个过程: 发送命令-〉命令排队-〉命令执行-〉返回结果 这个过程称为Round trip time(简称RTT, 往返时间),Redis提供许多批量操作的命令,如MSET/MGET/HMSET/HMGET等等,这些命令存在的意义是减少维护网络连接和传输数据所消耗的资源和时间。但大部分命令(如hgetall,并没有mhgetall)不支持批量操作,需要消耗N次RTT(Round trip time往返时间) ,这个时候需要pipeline来解决这个问题。

然而,如果客户端要连续执行的多次操作无法通过Redis命令组合在一起,例如: SET a "abc" INCR b HSET c name "hi"

此时便可以使用Redis提供的pipelining功能来实现在一次交互中执行多条命令。使用pipelining时,只需要从客户端一次向Redis发送多条命令(以\\r\\n)分隔,Redis就会依次执行这些命令,并且把每个命令的返回按顺序组装在一起一次返回,比如: $ (printf "PING\\r\\nPING\\r\\nPING\\r\\n"; sleep 1) | nc localhost 6379 +PONG +PONG +PONG 大部分的Redis客户端都对Pipelining提供支持,所以开发者通常并不需要自己手工拼装命令列表。 Pipelining的优势 管道技术最显著的优势是提高了 redis 服务的性能。 Pipelining的局限性 Pipelining只能用于执行连续且无相关性的命令,当某个命令的生成需要依赖于前一个命令的返回时,就无法使用Pipelining了。


分享到:


相關文章: