redis 事务之watch

来源:互联网 发布:什么是数据库事物 编辑:程序博客网 时间:2024/06/05 22:39

原文链接:http://ivhong.com/?p=166

事务保证原子性操作,在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-cli查看 watchkey 的结果,发现也仅仅第一个事务被正确执行了。