redis分布式锁的一个简单直接的实现方法就是用 SET NX 命令设置一个设定了存活周期 TTL 的 Key 来获取锁,通过删除 Key 来释放锁,通过存活周期来避免死锁。不过这个方法存在单点故障风险,如果部署了 master/slave 节点,则在特定条件下可能会导致安全性方面的冲突,比如:

  1. 客户端 A 从 master 节点获得锁
  2. master 节点在将 key 复制到 slave 节点之前崩溃了
  3. slave 节点提升为新的 master 节点
  4. 客户端 B 从新的 master 节点获得了锁,而这个锁实际上已经由客户端 A 所持有,导致了系统中有两个客户端在同一时间段内持有同一个互斥锁,破坏了互斥锁的安全性。

redis官方给出一个高可用分布式锁的实现:https://redis.io/topics/distlock

在 Redlock 算法中,通过类似于下面这样的命令进行加锁: SET resource_name my_random_value NX PX 30000

建立一个有 N(N 为奇数)个节点的redis集群,这种情况下,一个客户端获得锁和释放锁的算法如下:

  1. 先获取当前时间戳 timestamp_1,以毫秒为单位。
  2. 以相同的 Key 和随机数值,依次从 N 个节点获取锁,每次获取锁都设置一个超时,超时时限要保证小于所有节点上该锁的自动释放时间,以免在某个节点上耗时过长,通常都设的比较短。
  3. 客户端将当前时间戳减去第一步中的时间戳 timestamp_1,计算获取锁总消耗时间。只有当客户端获得了半数以上节点的锁,而且总耗时少于锁存活时间,该客户端才被认为已经成功获得了锁。
  4. 如果获得了锁,则其存活时间为开始预设锁存活时间减去获取锁总耗时间。
  5. 如果客户端不能获得锁,则应该马上在所有节点上解锁。
  6. 如果要重试,则在随机延时之后重新去获取锁。
  7. 获得了锁的客户端要释放锁,在所有节点上解锁即可。

Redlock 算法不需要保证 Redis 节点之间的时钟是同步的(不论是物理时钟还是逻辑时钟),这点和传统的一些基于同步时钟的分布式锁算法有所不同。

Redis分布式锁实现的更多相关文章

  1. 利用redis分布式锁的功能来实现定时器的分布式

    文章来源于我的 iteye blog http://ak478288.iteye.com/blog/1898190 以前为部门内部开发过一个定时器程序,这个定时器很简单,就是配置quartz,来实现定 ...

  2. Redis分布式锁

    Redis分布式锁 分布式锁是许多环境中非常有用的原语,其中不同的进程必须以相互排斥的方式与共享资源一起运行. 有许多图书馆和博客文章描述了如何使用Redis实现DLM(分布式锁管理器),但是每个库都 ...

  3. redis分布式锁和消息队列

    最近博主在看redis的时候发现了两种redis使用方式,与之前redis作为缓存不同,利用的是redis可设置key的有效时间和redis的BRPOP命令. 分布式锁 由于目前一些编程语言,如PHP ...

  4. redis咋么实现分布式锁,redis分布式锁的实现方式,redis做分布式锁 积极正义的少年

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...

  5. spring boot redis分布式锁

    随着现在分布式架构越来越盛行,在很多场景下需要使用到分布式锁.分布式锁的实现有很多种,比如基于数据库. zookeeper 等,本文主要介绍使用 Redis 做分布式锁的方式,并封装成spring b ...

  6. Redis分布式锁的正确实现方式

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...

  7. Redis分布式锁---完美实现

    这几天在做项目缓存时候,因为是分布式的所以需要加锁,就用到了Redis锁,正好从网上发现两篇非常棒的文章,来和大家分享一下. 第一篇是简单完美的实现,第二篇是用到的Redisson. Redis分布式 ...

  8. redis分布式锁实践

    分布式锁在多实例部署,分布式系统中经常会使用到,这是因为基于jvm的锁无法满足多实例中锁的需求,本篇将讲下redis如何通过Lua脚本实现分布式锁,不同于网上的redission,完全是手动实现的 我 ...

  9. Redis分布式锁的try-with-resources实现

    Redis分布式锁的try-with-resources实现 一.简介 在当今这个时代,单体应用(standalone)已经很少了,java提供的synchronized已经不能满足需求,大家自然 而 ...

  10. 关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁

    首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说方法.变量. 在一个进程中,也就是一个jvm 或者说应用中,我们很容易去处理控制,在j ...

随机推荐

  1. PostgreSQL进程和内存结构

    PostgreSQL数据库启动时,会先启动一个叫做Postmaster的主进程,还会fork一些辅助子进程,这些辅助子进程各自负责一部分功能,辅助子进程分类如下: $ ps -ef | grep po ...

  2. Linux只下载不安装软件包

    有时我们并不需要安装软件而只要下载软件包. 包格式 命令 命令所属包 命令下载格式 rpm yumdownloader yum-utils yumdownloader package_name deb ...

  3. 在vue项目中使用sass

    如果想开发移动端项目,那么适配的时候sass必不可缺,但是 npm  安装sass时候总是报错失败! 研究半天发现可以解决的方法,亲测有效 1.先换成淘宝镜像再安装 npm install -g cn ...

  4. oracle的case when的用法和decode函数的用法

    oracle中,我们要使用case when时,要怎样使用 如下测试数据,我要把ClassId 的1变成一班,2变成二班,3变成三班,那sql要怎样写呢? 1.case when的用法 -- orac ...

  5. java 数据溢出和编译错误的差别

    int a=100000000000;编译错误,超出int范围 int a=2100000000; int b=a*12020200;数据溢出,a并未溢出,但b在通过a计算后的数据溢出 long e= ...

  6. 尚学堂java 参考答案 第八章

    一.选择题 1.BD 解析:B:Integer是对象,所以默认的应该是null对象.D使用的是自动装箱 2.A 解析:String类的对象是final型,是不能修改的,concat()方法是生成一个新 ...

  7. 1.3 CPU简介

    目录 CPU的功能模块 cpu总线 CPU寄存器 16位cpu的寄存器组 32位cpu的寄存器组 64位cpu的寄存器组 CPU的功能模块 CPU从逻辑上可以划分成3个模块,分别是控制单元.运算单元和 ...

  8. 【转载】JVM系列一:JVM内存组成及分配

    java内存组成介绍:堆(Heap)和非堆(Non-heap)内存 按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时 ...

  9. MeshLab 编译

    1.需要以下:  MeshLab 1.3.3  下载地址 http://sourceforge.net/projects/meshlab/files/meshlab Win7 X64  Visual ...

  10. Spring MVC中注解: @ModelAttribute 与@RequestParam区别

    相关链接 : https://blog.csdn.net/huang343/article/details/77491096