Skip to main content

Command Palette

Search for a command to run...

关于redis分布式锁入门

Updated
1 min read
关于redis分布式锁入门

原理

单一实例下:使用setnx命令(在key不存在时,创建并设置value 返回1,key存在时,会返回0)来获取锁。

应用

以扣库存为例,使用锁能够有效保证不会被超卖;

  • 基础版方案:数据库锁

    SELECT stock from goods where ID =1 for update;
    update  goods set stock=stock-1 where id=1 and stock=10
    // 正常情况下看你业务需求,如果能够在落库前确认库存的话,上面这句话后面的stock=10能够限定库存锁定值
    // 如果不使用这个stock=10的话,会有一定的副作用,比如说常见的,多线程轮扣
    
  • redis 版v0

​ 使用setnx写入一个键值,如果成功则表明获取到锁,执行业务;对于没有获取到锁的,则会轮询获取。

            int waitIntervalMs = 50;//间隔等待时长 毫秒
            string lockKey = "lock_key:" + key; 
            DateTime begin = DateTime.Now;
            while (true)
            {
                if (redisClient.SetNX(lockKey, new byte[] { 1 }) == 1)
                {
                    redisClient.Expire(lockKey, expirySeconds);
                    return true;
                } 
                //不等待锁则返回
                if (waitSeconds <= 0)
                    break;

                if ((DateTime.Now - begin).TotalSeconds >= waitSeconds)//等待超时
                    break;

                System.Threading.Thread.Sleep(waitIntervalMs);
            }
            return false;

不管是该业务成功、失败或者异常,需要确保该锁在周期结束后能被释放

  • redis 版v1

    V0版本存在的缺陷:比较致命的是可能会出现,任务还未完成,锁就超时了,导致key被回收了,那么能不能将锁的申请时间作为值进行存储呢?

    int waitIntervalMs = 200;//间隔等待时长 毫秒 设置成足够长,至少要超过数据库的超时响应时间 string lockKey = "lock_key:" + key; DateTime begin = DateTime.Now; DateTime now = DateTime.Now; while (true) { //在key值存在的情况下 if(redisclient.ExistKey(lockKey)) { //如果key对应的value值+超时时间后小于当前时间,则移除key值,让业务正常运行 if(Convert.ToDateTime(redisclient.GetKey(lockkey).Value)+TimeLimit<now){ redisclient.remove(lockkey); } } if (redisClient.SetNX(lockKey, now.tostring()) == 1) { redisClient.Expire(lockKey, expirySeconds); return true; } //不等待锁则返回 if (waitSeconds <= 0) break;

    if ((DateTime.Now - begin).TotalSeconds >= waitSeconds)//等待超时 break;

    System.Threading.Thread.Sleep(waitIntervalMs);

} return false; ```

遗留的问题

在单个redis实例下,上述代码工作都ok,如果存在redis集群,且master挂掉的情况,那么这个锁一定锁不住

More from this blog

A

Agile Robin

35 posts

living an Awesome Life