redis watch 乐观锁实现秒杀 /防止超卖
在 Redis 中使用 watch 命令可以决定事务是执行还是回滚。一般而言,可以在 multi 命令之前使用 watch 命令监控某些键值对,然后使用 multi 命令开启事务,执行各类对数据结构进行操作的命令,这个时候这些命令就会进入队列。
当 Redis 使用 exec 命令执行事务的时候,它首先会去比对被 watch 命令所监控的键值对,如果没有发生变化,那么它会执行事务队列中的命令,提交事务;如果发生变化,那么它不会执行任何事务中的命令,而去事务回滚。无论事务是否回滚,Redis 都会去取消执行事务前的 watch 命令。
function testwatch(){
$redis = redis();
$mywatchkey = $redis->get("mywatchkey");
$rob_total = 100; //抢购数量
if($mywatchkey<$rob_total){
$redis->watch("mywatchkey");
$redis->multi();
//设置延迟,方便测试效果。
sleep(2);
//插入抢购数据
$redis->hSet("mywatchlist","user_id_".mt_rand(1, 9999),time());
$redis->set("mywatchkey",$mywatchkey+1);
$rob_result = $redis->exec();
if($rob_result){
$mywatchlist = $redis->hGetAll("mywatchlist");
echo "抢购成功!<br/>";
echo "剩余数量:".($rob_total-$mywatchkey-1)."<br/>";
echo "用户列表:<pre>";
var_dump($mywatchlist);
}else{
echo "手气不好,再抢购!";exit;
}
}
}
不知为何 在上述php测试中一直无法成功实现watch回滚功能
但是在cli中 操作watch可以
估计应是连接问题?
/*
* By default each template method call creates a new connection - so
* WATCH, MUTLI, EXEC, UNWATCH won't work because of the missing
* context. To make use of transaction support use SessionCallback which
* reuses the underlying connection.
*/
missing context?
终端1
127.0.0.1:6379> get fffffaa
"1280"
127.0.0.1:6379> watch fffffaa
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set fffffaa 9999
QUEUED
127.0.0.1:6379> exec
(nil)
终端2
中间时点set即可测试
Tags : 本文未设置标签
您可以自由的转载和修改,但请务必注明文章来源并且不可用于商业目的。
本站大部分内容收集于互联网,如果有侵权内容、不妥之处,请联系删除。敬请谅解!