• 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 单节点上完成了分布式锁的加锁和解锁。

     
  • 相关阅读:
    applicationContext.xml 文件头报错Referenced file contains errors
    oracle与mysql创建表时的区别
    Java 8 Stream
    Java 8 默认方法
    Java 8 函数式接口
    java 链表
    不完整的类型问题解决
    VScode 目录影藏某些文件不显示
    小姨多鹤 电视剧有感
    matlab 简单显示多边形和线条和点
  • 原文地址:https://www.cnblogs.com/KL2016/p/16576535.html
Copyright © 2020-2023  润新知