专栏首页dotnet & java分布式Redis的分布式锁 Redlock

分布式Redis的分布式锁 Redlock

链接 Distributed locks with Redis

引言

之前自己在用redis来实现分布式锁的时候都是基于单个Redis实例,也就是说Redis本身是有单点故障的,Redis的官方文档介绍了一种"自认为"合理的算法,Redlock来实现分布式Redis下的分布式锁。

Martin Kleppmann写了一篇文章分析Redlock。然后redis的作者写了一篇反驳的文章这里。加油。

Redlock实现库

虽然后面的算法是一样的,不过这个点赞数确实服。

单点Redis锁

先简单回顾一下单点的Redis锁是怎么实现的。

获取锁

SET resource_name my_random_value NX PX 30000

客户端A在Redis上设置一个特定的键值对,同时给一个超时时间(避免死锁)。其他客户端在访问的时候先看看这个key是否已经存在,并且值等于my_random_value。如果已存在就等待,否则就获取成功,执行业务代码。resource_namemy_random_value是所有客户端都知道并且共享的。

释放锁

if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

对比key获取到的对应的value是否相等,如果相等,就删除(释放),否则就返回失败。

之前也写过一篇文章

单点Redis锁的缺陷

这个缺陷其实很明显,如果只有一个Redis实例,这个挂了,所有依赖他的服务都挂了。显然不太适合大型的应用。

简单的Redis主从架构碰到的问题

为了避免单点故障,我们给Redis做一个Master/Slave的主从架构,一个Master,一台Slave。下面就会碰到这么一个问题。下面是使用场景。

  1. 客户端A在Master上获取到一个锁。
  2. Master把这个数据同步到Slave的时候挂了(因为Master和Slave之间同步是异步的)。
  3. Slave变成了Master。
  4. 客户端B通过相同的key,和value获取到锁。分布式锁失效

Redlock算法

假设我们有N(假设5)个Redis master实例,所有节点相互独立,并且业务系统也是单纯的调用,并没有什么其他的类似消息重发之类的辅助系统。下面来模拟一下算法:

  1. 客户端获取服务器当前的的时间t0,毫秒数。
  2. 使用相同的key和value依次向5个实例获取锁。客户端在获取锁的时候自身设置一个远小于业务锁需要的持续时间的超时时间。举个例子,假设锁需要10秒,超时时间可以设置成比如5-50毫秒。这个避免某个Redis本身已经挂了,但是客户端一直在尝试获取锁的情况。超时了之后就直接跳到下一个节点。
  3. 客户端通过当前时间(t1)减去t0,计算获取锁所消耗的时间t2(=t1-t0)。只有t2小于锁的业务有效时间(也就是第二步的10秒),并且,客户端在至少3(5/2+1)台上获取到锁我们才认为锁获取成功。
  4. 如果锁已经获取,那么锁的业务有效时间为10s-t2。
  5. 如果客户端没有获取到锁,可能是没有在大于等于N/2+1个实例上获取锁,也可能是有效时间(10s-t2)为负数,我们就尝试去释放锁,即使是并没有在那个节点上获取到。

锁的释放

释放比较简单,直接删除所有实例上对应的key就好。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 用Portable.BouncyCastle来进行加解密的代码demo

    这里对之前对接的公司中的代码demo做一个总结,原本为清一色的java,哈哈。这里都转成C#。用到的库是Portable.BouncyCastle。官网。之前也...

    _淡定_
  • 免密登录

    抄来的。。找不到原文链接了。。 A为本地主机(即用于控制其他主机的机器) ; B为远程主机(即被控制的机器Server), 假如ip为172.24.253....

    _淡定_
  • centos通过yum安装mysql

    前天按照Oracle上的文档装了一遍mysql,选了最新8.0的版本,后来出现一些问题,网上搜答案,出来的基本还是5.x版本的解决方案,并不适用8.0版本。然后...

    _淡定_
  • 深入Spring Boot (十一):整合Redis详解

    Spring Boot为Redis的Lettuce和Jedis客户端库提供了基本的自动配置,并且可以使用Spring Data Redis完成更多的操作。本篇将...

    JavaQ
  • Redis基础知识点面试手册

    Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。

    后端技术漫谈
  • 面试进阶必问的Redis,看这篇就够了!

    Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。

    乔戈里
  • 如何在Ubuntu 16.04上使用Stunnel加密流量到Redis

    Redis是一个开源键值数据存储,使用内存存储模型和可选的磁盘写入来实现持久性。它具有事务,发布/订阅消息传递模式以及其他功能之间的自动故障转移功能。Redis...

    陈树丶
  • Redis字符串数据结构的使用场景

    各位晚上好,这几天复习一下Redis中的数据结构。 首先,字符串类型是Redis最基础的数据结构。首先,键(key)都是字符串类型,而且在Redis中的其他数据...

    企鹅号小编
  • 刘春泉:大数据时代个人信息的法律保护

    大数据文摘
  • JVM 内存结构解析

    以前的方法区(或永久代),用来存放class,Method等元数据信息,但在JDK1.8已经没有了,取而代之的是MetaSpace(元空间),元空间不在虚拟机里...

    CoderJed

扫码关注云+社区

领取腾讯云代金券