redis 事务之watch

事务保证原子性操作,在redis 中实现事务和mysql中实现事务的方法有些不一样。
在 mysql中实现事务,一般是启动一个事务,然后执行 select ... for update 对某个要操作行进行锁定,然后如果并发的进程处理到锁定的行时,判定改行是否被其他的进程正在读(被锁定),如果是,则等待锁释放,然后继续执行结下来的操作,这也就是所谓的悲观锁。
在redis中实现事务也是有多个方法的,比如用 watch 监控某个key是否被其他的进程修改,watch乐观锁的实现方案,也就是说,先假定所有的进程之间的数据操作之间没有任何交集,执行一系列的操作,在最后提交的时候,如果发现被监控的key已经被其他的进程修改了(前面的假定失败),则提交时则返回false。
php中用redis 的 watch 实现的代码如下:

<?php
//创建redis连接
$redis = new \Redis(); 
$redis->connect('127.0.0.1', 6379);

//被监控的键
$key = 'watchkey';
//监控 $key,一定要在事务前监控这个键,因为在执行 multi 命令后,所有的命令将会进入到一个redis队列,然后保证这些命令可以不被其他程序打扰的情况下依次执行,这也是redis实现原子操作的方法
$redis->watch($key);

//启用原子操作(事务)
$redis->multi();
//为了测试结果,休眠3秒
sleep(3);
//修改被监控的键值,incr 是redis 的计数器,原子性操作,每次执行这个命令,将给 $key 自增 1
$redis->incr($key);
//在事务内得所有操作都将返回 redis 连接对象,只有在执行 exec 返回结果中,所有的返回数据将放到数组中返回
$redis->get($key);

//执行事务,如果事务执行失败则返回false,正确则返回事务中的所有返回结果
$r = $redis->exec();
var_dump($r);

把上面的程序保存到t.php中,然后在命令行执行三次,等待执行结果:
redis事务之watch
我们发现,只有第一次执行是成功的,接下来执行的都是失败的。在redis-cli查看 watchkey 的结果,发现也仅仅第一个事务被正确执行了。

此条目发表在redis分类目录,贴了, , 标签。将固定链接加入收藏夹。