• Redis 实现分布式锁


    redis 实现分布式锁机制原理:

    Redis 的 SET 命令有个 NX 参数可以实现「key不存在才插入」,所以可以用它来实现分布式锁:

    • 如果 key 不存在,则显示插入成功,可以用来表示加锁成功;
    • 如果 key 存在,则会显示插入失败,可以用来表示加锁失败。

    =====

    基于 Redis 节点实现分布式锁时,对于加锁操作,我们需要满足三个条件。

    • 加锁包括了读取锁变量、检查锁变量值和设置锁变量值三个操作,但需要以原子操作的方式完成,所以,我们使用 SET 命令带上 NX 选项来实现加锁;
    • 锁变量需要设置过期时间,以免客户端拿到锁后发生异常,导致锁一直无法释放,所以,我们在 SET 命令执行时加上 EX/PX 选项,设置其过期时间;
    • 锁变量的值需要能区分来自不同客户端的加锁操作,以免在释放锁时,出现误释放操作,所以,我们使用 SET 命令设置锁变量值时,每个客户端设置的值是一个唯一值,用于标识客户端;

    满足这三个条件的分布式命令如下:

    SET lock_key unique_value NX PX 10000  
    详解:
    • lock_key 就是 key 键;
    • unique_value 是客户端生成的唯一的标识,区分来自不同客户端的锁操作;
    • NX 代表只在 lock_key 不存在时,才对 lock_key 进行设置操作;
    • PX 10000 表示设置 lock_key 的过期时间为 10s,这是为了避免客户端发生异常而无法释放锁。
    • (而解锁的过程就是将 lock_key 键删除(del lock_key),但不能乱删,要保证执行操作的客户端就是加锁的客户端。所以,解锁的时候,我们要先判断锁的 unique_value 是否为加锁客户端,是的话,才将 lock_key 键删除。)

    解锁是有两个操作,这时就需要 Lua 脚本来保证解锁的原子性,因为 Redis 在执行 Lua 脚本时,可以以原子性的方式执行,保证了锁释放操作的原子性。

    // 释放锁时,先比较 unique_value 是否相等,避免锁的误释放
    if redis.call("get",KEYS[1]) == ARGV[1] then
        return redis.call("del",KEYS[1])
    else
        return 0
    end

    这样一来,就通过使用 SET 命令和 Lua 脚本在 Redis 单节点上完成了分布式锁的加锁和解锁。

     
  • 相关阅读:
    Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(四)
    中国B2B行业将进入后平台时代
    做产品经理 而不是功能经理(转淘宝鬼脚七)
    全球最值的学习的100个网站
    gridview 内的button 用法
    框架内 FRAME的源src如何根据条件而变化?C#解决方案
    一般中小企网络出口的后备线路(adsl做后备)
    Windows server 2012_远程_没有远程桌面授权服务器可以提供许可证
    访问网站返回常见的状态码200,404等表示什么意思(转)
    站长学习 一 Robots简单认识
  • 原文地址:https://www.cnblogs.com/KL2016/p/16576535.html
Copyright © 2020-2023  润新知