• redis中使用 check-and-set 操作实现乐观锁


    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 监视了一个带过期时间的键, 那么即使这个键过期了, 事务仍然可以正常执行

    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)即可。

  • 相关阅读:
    ThinkJS框架入门详细教程(一)开发环境
    为什么要使用云盘?
    博客使用BOS上传图片
    网站第三方评论对比
    Angular定义服务-Learn By Doing
    原生Ajax总结
    JavaScript事件概览
    Angular学习-指令入门
    Angular中ngCookies模块介绍
    Angular Service入门
  • 原文地址:https://www.cnblogs.com/csd97/p/6635540.html
Copyright © 2020-2023  润新知