Redis的锁来缓解并发请求

本文最后更新于:4 年前

Redis 锁 缓解并发

  1. 简单实现

    Redis 锁主要利用 Redis 的 setnx 命令实现

    • 加锁命令:SETNX key value,当键不存在时,对键进行设置操作并返回成功,否则返回失败。KEY 是锁的唯一标识,一般按业务来决定命名。
    • 解锁命令:DEL key,通过删除键值对释放锁,以便其他线程可以通过 SETNX 命令来获取锁。
    • 锁超时:EXPIRE key timeout, 设置 key 的超时时间,以保证即使锁没有被显式释放,锁也可以在一定时间后自动释放,避免资源被永远锁住。

    代码编写:

    1
    2
    3
    4
    5
    6
    if (Redis::setnx("my:lock", 1)) {
    Redis::expire("my:lock", 10);
    // ... do something

    Redis::del("my:lock")
    }

    官方推荐的写法(建议用这种写法):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    while (true)
    {
    if(redisLock($token))
    {
    //业务内容
    unlock($token);
    break;
    }
    }

    function redisLock($token)
    {
    return Redis::set("my:lock", $token, "ex", "5", "nx");
    }

    function unlock($token)
    {
    $script = "if redis.call('get',KEYS[1]) == ARGV[1]
    then return redis.call('del',KEYS[1])
    else return 0
    end";
    return Redis::eval($script,1,'my:lock',$token);
    }
    • 这里的 token 是一个随机数,当 lock 的时候,往 redis 的 my:lock 中存的是这个 token,unlock 的时候,先 get 一下 lock 中的 token,如果和我要删除的 token 是一致的,说明这个锁是之前我 set 的,否则的话,说明这个锁已经过期,是别人 set 的,我就不应该对它进行任何操作。

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!