• Redis实现分布式锁


    布式锁实现的三个核心要素:加锁、解锁、锁超时。

    一、Redis实现分布式锁基本原理

    1.1、Redis具体实现

    情景:存在多台JVM需要同时对某一商品(id)进行操作。

    • 加锁:使用setnx命令,伪代码:setnx(id,value)
        返回1,说明key不存在,线程抢锁成功;
        返回1,说明key已存在,线程抢锁失败。
       注意:setnx(id,value)中key为操作商品的id,value值可用于防止误删锁,下文有提到。

    • 解锁:使用del命令,伪代码:del(id)

    • 锁超时:如果一个得到锁的线程在执行任务的过程中挂掉,来不及显式地释放锁,该资源将会被永远占用,其他线程将无法访问。
         可以使用expire为key设置一个超时时间,与setnx命令一起执行(setnx不支持超时参数),用以保证即使未被显式释放,该锁也可在一定时间后自动释放。伪代码:expire(key, 30)。

    1.2、上述实现存在的问题

    • 非原子性操作
        加锁setnx和锁超时expire两个命令未非原子性操作,当执行加锁setnx后,若因网络或客户端问题锁超时expire命令未成功执行时,锁将无法被释放。
      解决方案:
        使用set命令取代setnx和expire命令。setnx本身不支持设置超时时间。在Redis 2.6.12以上版本为set指令增加了可选参数,伪代码:set(key, value, expire)。

    • 误删锁
      设想如下情形:
        (1)JVM1使用set(001, 002, 30)成功获取锁,并设置超时时间为30s;
        (2)JVM1开始数据处理,处理时间已经超过了30s...
        (3)服务器检测到(001, 002, 30)数据超时,将自动执行del进行数据删除,此时JVM1还在数据处理...
        (4)此时,JVM2使用set(001, 002, 30)成功获取锁,并设置超时时间为30s;
        (5)JVM2开始数据处理。与此同时,JVM1处理完成,操作提交后,根据商品id001,执行了del;
          到此,JVM1成功误删了JVM2的锁。
      解决方案:
        del数据之前,增加锁判断机制:判断要删除的锁是否属于本线程。操作流程:
        (1)加锁:set(id, threadId,expire),其中value为当前线程ID;
        (2)解锁:执行del命令时,根据id和threadId数据判断该锁是否仍属于本线程。是,则删除。

    • 并发问题
        基于误删锁的前提下,由于我们无法确定程序成功处理完成数据的具体时间,这就为超时时间的设置提出了难题。设置时间过长、过短都将影响程序并发的效率。
      解决方案:JVM1需要自己判断在超时时间内是否完成数据处理,如未完成,应请求延长超时时间。具体操作:
        为获取锁的锁的线程开启一个守护线程。当29秒时(或更早),线程A还没执行完,守护线程会执行expire指令,为这把锁“续命”20秒。守护线程从第29秒开始执行,每20秒执行一次。当线程A执行完任务,会显式关掉守护线程。

        另一种情况:如果节点1 忽然断电,由于线程A和守护线程在同一个进程,守护线程也会停下。当过了超时时间后,没有守护进程的“续命”,锁将自动释放。

  • 作者: DeepInThought
    出处: https://www.cnblogs.com/DeepInThought
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    初涉Android蓝牙开发
    android真机调试方法
    BizTalk Server 系列文章目录
    【译文】ExtJS 4.1性能预览
    【译】ExtJS 4.1会带来什么
    cocos2dx 如何使用Visual Studio 2010和xcode 4混合编写手机游戏
    Mac osx 下让android 模拟器横屏
    c++ int convert to std::string 转换成std::string
    离ExtJS 4.1 beta发布只剩26个bug了
    Window.ShowModalDialog使用详解
  • 原文地址:https://www.cnblogs.com/DeepInThought/p/11072966.html
  • Copyright © 2020-2023  润新知