redis中使用 check-and-set 操作实现乐观锁
2017-02-13 15:45
387 查看
redis中使用 check-and-set 操作实现乐观锁
转载2015-03-1016:23:35
WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为。
被 WATCH 的键会被监视,并会发觉这些键是否被改动过了。 如果有至少一个被监视的键在 EXEC 执行之前被修改了,
那么整个事务都会被取消, EXEC 返回空多条批量回复(null multi-bulk reply)来表示事务已经失败。
举个例子, 假设我们需要原子性地为某个值进行增 1 操作(假设 INCR 不存在)。
首先我们可能会这样做:
val = GET mykey val = val + 1 SET mykey $val
上面的这个实现在只有一个客户端的时候可以执行得很好。 但是, 当多个客户端同时对同一个键进行这样的操作时, 就会产生竞争条件。
举个例子, 如果客户端 A 和 B 都读取了键原来的值, 比如 10 , 那么两个客户端都会将键的值设为 11 , 但正确的结果应该是 12才对。
有了 WATCH , 我们就可以轻松地解决这类问题了:
WATCH mykey val = GET mykey val = val + 1 MULTI SET mykey $val EXEC
使用上面的代码, 如果在 WATCH 执行之后, EXEC 执行之前,
有其他客户端修改了 mykey 的值, 那么当前客户端的事务就会失败。 程序需要做的, 就是不断重试这个操作, 直到没有发生碰撞为止。
这种形式的锁被称作乐观锁, 它是一种非常强大的锁机制。 并且因为大多数情况下, 不同的客户端会访问不同的键, 碰撞的情况一般都很少, 所以通常并不需要进行重试。
了解 WATCH
WATCH 使得 EXEC 命令需要有条件地执行:事务只能在所有被监视键都没有被修改的前提下执行, 如果这个前提不能满足的话,事务就不会被执行。
如果你使用 WATCH 监视了一个带过期时间的键, 那么即使这个键过期了, 事务仍然可以正常执行, 关于这方面的详细情况,请看这个帖子: http://code.google.com/p/redis/issues/detail?id=270
WATCH 命令可以被调用多次。 对键的监视从 WATCH 执行之后开始生效,
直到调用 EXEC 为止。
用户还可以在单个 WATCH 命令中监视任意多个键, 就像这样:
redis> WATCH key1 key2 key3 OK
当 EXEC 被调用时, 不管事务是否成功执行, 对所有键的监视都会被取消。
另外, 当客户端断开连接时, 该客户端对键的监视也会被取消。
使用无参数的 UNWATCH 命令可以手动取消对所有键的监视。 对于一些需要改动多个键的事务, 有时候程序需要同时对多个键进行加锁, 然后检查这些键的当前值是否符合程序的要求。
当值达不到要求时, 就可以使用 UNWATCH 命令来取消目前对键的监视, 中途放弃这个事务, 并等待事务的下次尝试。
使用 WATCH 实现 ZPOP
WATCH 可以用于创建 Redis 没有内置的原子操作。举个例子, 以下代码实现了原创的 ZPOP 命令, 它可以原子地弹出有序集合中分值(score)最小的元素:
WATCH zset element = ZRANGE zset 0 0 MULTI ZREM zset element EXEC
程序只要重复执行这段代码, 直到 EXEC 的返回值不是空多条回复(null multi-bulk reply)即可。
相关文章推荐
- redis中使用 check-and-set 操作实现乐观锁
- 网站后台登录aspcms 提示错误号:-2147467259,错误描述:操作必须使用一个可更新的查询。sql=update AspCms_Content set TimeStatus=0 where TimeStatus=1 and Timeing <= 解决方法。
- 使用ThinkPHP扩展,实现Redis的CURD操作。
- java使用jeids实现redis2.6的String操作(2)
- Redis使用lua脚本实现increase + expire 的原子操作
- java使用jeids实现redis2.6的list操作(2)
- java使用jeids实现redis2.6的GEO(地理位置)数据结构的操作
- java使用jeids实现redis2.6的String操作(1)
- 使用redis乐观锁实现秒杀
- Java Jedis操作Redis示例(三)——setnx/getset实现分布式锁
- redis 的使用 (sort set排序集合类型操作)
- Lua 脚本 Lua 脚本功能是 Reids 2.6 版本的最大亮点, 通过内嵌对 Lua 环境的支持, Redis 解决了长久以来不能高效地处理 CAS (check-and-set)命令的缺点,
- jface databinding:使用CheckboxTableViewer实现表中(Set)对象与CheckTable中选中条目数据绑定
- java使用jeids实现redis2.6的list操作(4)
- Java中使用Jedis操作Redis的实现代码
- 使用ThinkPHP扩展,实现Redis的CURD操作。
- 使用Redis sorted set实现集合设置member过期
- 【Redis缓存机制】6.Set集合类型操作使用
- java使用jeids实现redis2.6的list操作(1)
- java使用jeids实现redis2.6的list操作(3)