tair分布式锁实现:https://yq.aliyun.com/articles/58928

redis分布式锁:https://www.cnblogs.com/jianwei-dai/p/6137896.html

https://blog.csdn.net/abbc7758521/article/details/77990048

                  分布式锁之Redis实现(最终版)

redis、zookeeper分布式锁安全性讨论:https://blog.csdn.net/jackcaptain1015/article/details/71157004

http://mp.weixin.qq.com/s/JTsJCDuasgIJ0j95K8Ay8w      http://mp.weixin.qq.com/s/4CUe7OpM6y1kQRK8TOC_qQ

使用setnx get getset实现分布式锁

多个进程执行以下Redis命令:

SETNX lock.foo <current Unix time + lock timeout + 1>

如果 SETNX 返回1,说明该进程获得锁,SETNX将键 lock.foo 的值设置为锁的超时时间(当前时间 + 锁的有效时间)。 
如果 SETNX 返回0,说明其他进程已经获得了锁,进程不能进入临界区。进程可以在一个循环中不断地尝试 SETNX 操作,以获得锁。

解决死锁

考虑一种情况,如果进程获得锁后,断开了与 Redis 的连接(可能是进程挂掉,或者网络中断),如果没有有效的释放锁的机制,那么其他进程都会处于一直等待的状态,即出现“死锁”。

上面在使用 SETNX 获得锁时,我们将键 lock.foo 的值设置为锁的有效时间,进程获得锁后,其他进程还会不断的检测锁是否已超时,如果超时,那么等待的进程也将有机会获得锁。

然而,锁超时时,我们不能简单地使用 DEL 命令删除键 lock.foo 以释放锁。考虑以下情况,进程P1已经首先获得了锁 lock.foo,然后进程P1挂掉了。进程P2,P3正在不断地检测锁是否已释放或者已超时,执行流程如下:

  • P2和P3进程读取键 lock.foo 的值,检测锁是否已超时(通过比较当前时间和键 lock.foo 的值来判断是否超时)
  • P2和P3进程发现锁 lock.foo 已超时
  • P2执行 DEL lock.foo命令
  • P2执行 SETNX lock.foo命令,并返回1,即P2获得锁
  • P3执行 DEL lock.foo命令将P2刚刚设置的键 lock.foo 删除(这步是由于P3刚才已检测到锁已超时)
  • P3执行 SETNX lock.foo命令,并返回1,即P3获得锁
  • P2和P3同时获得了锁

从上面的情况可以得知,在检测到锁超时后,进程不能直接简单地执行 DEL 删除键的操作以获得锁。

为了解决上述算法可能出现的多个进程同时获得锁的问题,我们再来看以下的算法。 
我们同样假设进程P1已经首先获得了锁 lock.foo,然后进程P1挂掉了。接下来的情况:

  • 进程P4执行 SETNX lock.foo 以尝试获取锁
  • 由于进程P1已获得了锁,所以P4执行 SETNX lock.foo 返回0,即获取锁失败
  • P4执行 GET lock.foo 来检测锁是否已超时,如果没超时,则等待一段时间,再次检测
  • 如果P4检测到锁已超时,即当前的时间大于键 lock.foo 的值,P4会执行以下操作 
    GETSET lock.foo <current Unix timestamp + lock timeout + 1>
  • 由于 GETSET 操作在设置键的值的同时,还会返回键的旧值,通过比较键 lock.foo 的旧值是否小于当前时间,可以判断进程是否已获得锁
  • 假如另一个进程P5也检测到锁已超时,并在P4之前执行了 GETSET 操作,那么P4的 GETSET 操作返回的是一个大于当前时间的时间戳,这样P4就不会获得锁而继续等待。注意到,即使P4接下来将键 lock.foo 的值设置了比P5设置的更大的值也没影响。

另外,值得注意的是,在进程释放锁,即执行 DEL lock.foo 操作前,需要先判断锁是否已超时。如果锁已超时,那么锁可能已由其他进程获得,这时直接执行 DEL lock.foo 操作会导致把其他进程已获得的锁释放掉,所以不需要再对锁进行处理。

public static boolean acquireLock(String lock) {
// 1. 通过SETNX试图获取一个lock
boolean success = false;
Jedis jedis = pool.getResource();
long value = System.currentTimeMillis() + expired + 1;
System.out.println(value);
long acquired = jedis.setnx(lock, String.valueOf(value));
//SETNX成功,则成功获取一个锁
if (acquired == 1)
success = true;
//SETNX失败,说明锁仍然被其他对象保持,检查其是否已经超时
else {
long oldValue = Long.valueOf(jedis.get(lock));

//超时
if (oldValue < System.currentTimeMillis()) {
String getValue = jedis.getSet(lock, String.valueOf(value));
// 获取锁成功
if (Long.valueOf(getValue) == oldValue)
success = true;
// 已被其他进程捷足先登了
else
success = false;
}
//未超时,则直接返回失败
else
success = false;
}
pool.returnResource(jedis);

return success;
}

分布式锁tair redis zookeeper,安全性的更多相关文章

  1. 分布式锁用Redis还是ZooKeeper?(转载)

    文章系网络转载,侵删. 来源:https://zhuanlan.zhihu.com/p/73807097 为什么用分布式锁?在讨论这个问题之前,我们先来看一个业务场景. 图片来自 Pexels 为什么 ...

  2. 分布式锁用Redis与Zookeeper的使用

    为什么用分布式锁?   在讨论这个问题之前,我们先来看一个业务场景: 系统A是一个电商系统,目前是一台机器部署,系统中有一个用户下订单的接口,但是用户下订单之前一定要去检查一下库存,确保库存足够了才会 ...

  3. 从分布式锁来看redis和zookpeer!

    从分布式锁来看redis和zookpeer! 目前网上大部分的基于zookpeer,和redis的分布式锁的文章都不够全面.要么就是特意避开集群的情况,要么就是考虑不全,读者看着还是一脸迷茫.坦白说, ...

  4. 分布式锁----浅析redis实现

    引言大概两个月前小伙伴问我有没有基于redis实现过分布式锁,之前看redis的时候知道有一个RedLock算法可以实现分布式锁,我接触的分布式项目要么是github上开源学习的,要么是小伙伴们公司项 ...

  5. 解析分布式锁之Redis实现(二)

    摘要:在前文中提及了实现分布式锁目前有三种流行方案,分别为基于数据库.Redis.Zookeeper的方案,本文主要阐述基于Redis的分布式锁,分布式架构设计如今在企业中被大量的应用,而在不同的分布 ...

  6. 分布式锁(redis/mysql)

    单台机器所能承载的量是有限的,用户的量级上万,基本上服务都会做分布式集群部署.很多时候,会遇到对同一资源的方法.这时候就需要锁,如果是单机版的,可以利用java等语言自带的并发同步处理.如果是多台机器 ...

  7. SpringBoot集成Redis分布式锁以及Redis缓存

    https://blog.csdn.net/qq_26525215/article/details/79182687 集成Redis 首先在pom.xml中加入需要的redis依赖和缓存依赖 < ...

  8. Java分布式:分布式锁之Redis实现

    Java分布式:分布式锁之Redis实现 分布式锁系列教程重点分享锁实现原理 Redis锁原理 核心命令 Redis分布式锁的原理是基于其SETNX命令,我们来看SETNX的解释. 实现过程 使用SE ...

  9. 【分布式锁】Redis实现可重入的分布式锁

    一.前言 之前写的一篇文章<细说分布式锁>介绍了分布式锁的三种实现方式,但是Redis实现分布式锁关于Lua脚本实现.自定义分布式锁注解以及需要注意的问题都没描述.本文就是详细说明如何利用 ...

随机推荐

  1. Selenium(Webdriver)自动化测试常问到的问题解答(转自:潜龙0318)

    今天朋友问我了几个关于Selenium自动化测试的问题,我看了一下感觉还比较典型.结合我以往自动化测试的经验,给出了一些儿粗浅的答案,希望能帮大家,如果大家有什么好的看法,希望相互交流,相互学习! ( ...

  2. 不允许有匹配 "[xX][mM][lL]" 的处理指令目标

    八月 , :: 上午 org.apache.tomcat.util.digester.SetPropertiesRule begin 警告: [SetPropertiesRule]{Server/Se ...

  3. MVC中关于 使用后台代码 检查 用户名是否已经被清册

    在 注册页面  NewUser 的 Controller中写以下代码 public  ActionResult GetUserIndataByUserName() { string UserName= ...

  4. 20135320赵瀚青LINUX第一章读书笔记

    第一章-Linux内核简介 Unix的历史 依旧被认为是最强大和最优秀的系统 由一个失败的操作系统Multics中产生 被移植到PDP-11型机中 由其他组织进一步开发 重写了虚拟内存系统,最终官方版 ...

  5. linux 块设备-整理(一)

    1. 基本概念: linux设备驱动开发详解(宋宝华): 字符设备与块设备 I/O 操作的不同如下. (1)块设备只能以块为单位接受输入和返回输出,而字符设备则以字节为单位. 大多数设备是字符设备,因 ...

  6. chrome调试工具

    Chrome调试面板 Chrome 开发者工具是一套内置在Google Chrome中Web开发和调试工具.使用开发者工具来重演,调试和剖析您的网站.其中常用的有Elements(元素面板).Cons ...

  7. openwrt中的append-ubi定义在哪里

    include/image-commands.mk 定义如下: define Build/append-ubi sh $(TOPDIR)/scripts/ubinize-image.sh \ $(if ...

  8. 翻翻git之---丰富多样的路由跳转开源库 ARouter

    转载请注明出处:王亟亟的大牛之路 有一段时间没更新博客了,最近也没学什么新东西,正好组里小伙在做路由跳转的一个"公共库",然后正好最近这样的轮子不少,我也就跟着看看,学习一下人家的 ...

  9. linux下错误 && 解决方法

    1.使用yum命令安装出现错误 Error: Cannot find a valid baseurl for repo: extras 解决方法: vi /etc/resolv.conf 在此文件最后 ...

  10. 第七篇:Spark SQL 源码分析之Physical Plan 到 RDD的具体实现

    /** Spark SQL源码分析系列文章*/ 接上一篇文章Spark SQL Catalyst源码分析之Physical Plan,本文将介绍Physical Plan的toRDD的具体实现细节: ...