redis为啥需要watch
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis为啥需要watch相关的知识,希望对你有一定的参考价值。
1、redis事物通过multi命令开始。这条命令总是返回ok。
2、然后用户可以执行多条指令,redis不会马上执行这些指令,还只是放入到队列中。
3、当执行exec指令时,所有的指令执行。
4、调用discard指令,将会flush事物队列,并且退出事物。
如下:redis
127.0.0.1:6379
multiokredis
127.0.0.1:6379
set
foo
1queuedredis
127.0.0.1:6379
incr
fooqueuedredis
127.0.0.1:6379
incr
fooqueuedredis
127.0.0.1:6379
exec1)
ok2)
(integer)
2
3)
(integer)
3
如以下:redis
127.0.0.1:6379
multiokredis
127.0.0.1:6379
set
t
13queuedredis
127.0.0.1:6379
lpop
tqueuedredis
127.0.0.1:6379
exec1)
ok2)
(error)
err
operation
against
a
keyholding
the
wrong
kind
of
value
对于这种err,需要客户端给予合理的提示。
需要注意的是,所有在队列中的指令都会被执行,redis不会终止指令的执行(
事物中有指令失败事物不会终止在这条失败的指令上
)。
三、mutil总是返回ok,然后调用get,set写数据,这些指令会被提交到队列,discard取消命令队列,不执行事物:
discard为取消命令队列。可以终断一个事物。不会有命令会被执行,并且连接的状态是正常的。
如:set
foo
1okmultiokincr
fooqueueddiscardokget
foo"1"
四、redis的optimistic
locking
using
check-and-set(乐观锁),实现get,set命令序列数据的原子性:
watch指令在redis事物中提供了cas的行为。
为了检测被watch的keys在是否有多个clients改变时引起冲突,这些keys将会被监控。
例如:一个key自增长(假设redis不提供incr的功能)
val
=
get
mykey
val
=
val
+
1
set
mykey
$val
以上指令执行,如果是单一的client,整个操作是没问题的。如果多个client在同一时间操作。如client
a与
client
b读取了老的值,假如是10,这个值在两个client将会被增长到11,最后set这个key值时,这个key最终是11还不是12.
watch能够很好的处理这种问题:
watch
mykey
val
=
get
mykey
val
=
val
+
1multiset
mykey
$valexec使用以上代码,
如果在执行watch与exec指令这段时间里有其它客户端修改此key值,此事物将执行失败。
以上形式的锁被称为乐观锁。 参考技术A 不知道你说的watch是啥意思,php操作redis很简单的,举个例子:
<?php
//连接本地的 Redis 服务
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
echo "Connection to server sucessfully";
//设置 redis 字符串数据
$redis->set("tutorial-name", "Redis tutorial");
// 获取存储的数据并输出
echo "Stored string in redis:: " . $redis->get("tutorial-name");
?>
这是操作字符串的,还有操作其他redis数据类型的。
要成功先确保你php有装redis扩展,并且本地redis服务正常跑着的。
如果没有解决你的问题的话,麻烦你解释一下问题吧,你看都没人回你,因为你问题不清楚啊。
如果解决了,就请采纳吧。本回答被提问者采纳
redis 事务 和 watch
原文:redis 事务 和 watch
一般的 事务简单来说就是 一系列的操作保证原子性,成功都成功~失败都失败。
但是!但是!但是! redis
的事务在执行中出错时,错的将会被忽略,队列之后的指令依然可以执行。一旦出现这种情况 需要手动回滚。
redis 的事务仅仅保证了所有的操作都会严格的 按照原子操作来执行,不保证所有的都是成功的,这需要开发者自己来约束。
开启和执行#
如何开启事物并开始执行
multi#
设定事务的开启位置,此指令执行后,后续的所有指令均加入到事务中。
exec#
设定事务的结束位置,同时执行事务。与multi成对出现,成对使用
注意#
加入事务的命令暂时到任务队列
中,没有立即执行,在一切顺利的情况下(在nulti 和 exec 之间没有出现error
)只有执行exec命令才开始执行。
取消事务#
将 multi
之后但还没有 exec
的事物取消掉
主动#
discard
终止当前事务定义,发生在multi之后,exec之前。
被动#
语法错误
在事务的定义阶段,也就是 multi
和 exec
之间存在语法错误,那么整个事务队列将会被删除。
当redis
事务开始执行,就不在乎是否全部成功,即使存在error
后面的也会执行,需要手动回滚。
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name monkey
QUEUED
127.0.0.1:6379> set gender male or female # 执行这行会报错
QUEUED
127.0.0.1:6379> get name
QUEUED
127.0.0.1:6379> exec
1) OK # name 设置成功了
2) (error) ERR syntax error # gender 失败
3) "monkey" # 错误之后的也会执行~ 这事务 很蛋疼~~
127.0.0.1:6379>
手动进行事务回滚#
记录状态#
将操作过程中被影响的数据提前备份记录
单数据:string
多数据:hash,list,set,zset
恢复状态#
使用之前备份的数据恢复事务操作之前的数据。
单数据:直接set(注意周边属性,例如时效)
多数据:修改对应值或整体克隆复制
事务的工作流程#
watch#
场景#
假如在线商城的某个货物售空了,此时有多个业务员可以进行补货操作。但是又希望在卖的商品不能超过100个,应该怎么办?
分析
这几个业务员不可能每次补货之前都沟通一下,因此必须要保证每次只能有一个人来操作数据,并且数据一旦被修改,就不需要其他人在修改了。一旦多个人同时修改,则只有一个人能修改成功。
解决方案#
对 key
添加监视锁,在执行exec
前如果 key
发生了变化,终止事务执行
watch key1 [key2…] # 可以同时监视多个变量
取消对所有key的监视
unwatch # 取消对所有key的监视
我们先对当前的 货物数
进行监视,对补货操作开启事务,如果在执行事务 exec
之前 数量变了,表示已经有人进行了补货操作,因此终止事务。如果一切顺利,成功的补货完成。
注意 在 watch 对象改变时,事务队列中所有的操作都不会被执行,就是说事务队列直接被销毁。
以上是关于redis为啥需要watch的主要内容,如果未能解决你的问题,请参考以下文章