zoukankan      html  css  js  c++  java
  • Redis用setnx+expire实现分布式锁存在什么隐患,如何改进?

    用Redis实现分布式锁,2.6.12之前版本方案:setnx加锁,del释放锁,如果锁没释放,设置过期时间,到了时间,del释放锁。但是,这会存在一些问题。

    1. setnx和expire不是原子操作一旦redis宕机,expire没有设置成功,锁就无法释放。只有一个请求的setnx可以成功,任何一个请求的expire都可以成功。请求比较密集,过期时间一直刷新,导致锁一直有效。
    2. 超时后,删除其他线程的锁。在线程A执行过程中,锁已释放,A还未在执行业务,但是还未删除锁。线程B获取锁执行业务,线程A执行完,A误删B的锁。
    3. 多个线程并发获取锁、释放锁。同一时间有线程A、B在访问同一代码块。

    对于上面的隐患,Redis已改善。下面,我们针对隐患逐一改善。

    1. Redis2.6.12以上版本,可以用set获取锁。set可以实现setnx和expire,这个是原子操作。
    2. Lua删除锁。Lua是原子操作。
    3. 让获取锁的线程开启一个守护线程,给线程还没执行完,又快要过期的锁续航。大概是这样的,线程A还没执行完,守护线程每当快过期时,延时expire时间。当线程A执行完,显示关闭守护线程。如果中间宕机,锁超过超时,守护线程也不在了,自动释放锁。
  • 相关阅读:
    python timeit模块用法
    boto3库限速
    golang-Beego-orm创建的坑
    Java07
    Java06
    Java04
    Java03
    c
    Mac 安装GCC
    命令: go build
  • 原文地址:https://www.cnblogs.com/ivy-xu/p/12613267.html
Copyright © 2011-2022 走看看