链接

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就好。

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

  1. 用Redis构建分布式锁-RedLock(真分布)

    在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现一个分布式锁管理器,但是这些库实现的方式差别很大,而且很多简单的实现其实只需采用稍微增 ...

  2. 【Redis】分布式锁RedLock

    普通实现 说道Redis分布式锁大部分人都会想到: 1.setnx+lua, 2.setkey value px milliseconds nx. - 获取锁(unique_value可以是UUID等 ...

  3. 基于Redis的分布式锁和Redlock算法

    1 前言 前面写了4篇Redis底层实现和工程架构相关文章,感兴趣的读者可以回顾一下: Redis面试热点之底层实现篇-1 Redis面试热点之底层实现篇-2 Redis面试热点之工程架构篇-1 Re ...

  4. C# Redis分布式锁(RedLock) - 多节点

    Redis单节点的分布式锁只需要注意三点就可以了: 1.加锁并设置锁的过期时间必须是原子操作; 2.锁的value值必须要有唯一性; 3.释放锁的时候要验证其value值,不是自己加的锁不能释放. 但 ...

  5. 身为一枚优秀的程序员必备的基于Redis的分布式锁和Redlock算法

    1 前言 今天开始来和大家一起学习一下Redis实际应用篇,会写几个Redis的常见应用. 在我看来Redis最为典型的应用就是作为分布式缓存系统,其他的一些应用本质上并不是杀手锏功能,是基于Redi ...

  6. Redis实现分布式锁

    http://redis.io/topics/distlock 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现一个分布式锁管理器,但 ...

  7. 基于Redis的分布式锁真的安全吗?

    说明: 我前段时间写了一篇用consul实现分布式锁,感觉理解的也不是很好,直到我看到了这2篇写分布式锁的讨论,真的是很佩服作者严谨的态度, 把这种分布式锁研究的这么透彻,作者这种技术态度真的值得我好 ...

  8. 【转】Redis学习笔记(五)如何用Redis实现分布式锁(2)—— 集群版

    原文地址:http://bridgeforyou.cn/2018/09/02/Redis-Dsitributed-Lock-2/ 单机版实现的局限性 在上一篇文章中,我们讨论了Redis分布式锁的实现 ...

  9. Redis做分布式锁

    在分布式系统中,在接口没有保证幂等性或者在某些场景下相同的服务需要有且仅有一个服务执行的情况下,需要使用分布式锁来保证系统的安全执行. 分布式锁的执行顺序,有服务A,分别部署了三个节点为A1.A2.A ...

随机推荐

  1. MySQL 高可用架构 之 MHA (Centos 7.5 MySQL 5.7.18 MHA 0.58)

    目录 简介 环境准备 秘钥互信 安装基础依赖包 安装MHA组件 安装 MHA Node组件 安装 MHA Manager 组件 建立 MySQL 一主三从 初始化 MySQL 启动MySQL 并简单配 ...

  2. CCNA 之 十二 Frame Relay 帧中继

    Fram Relay 帧中继 帧中继简介 VC.LMI.DLCI的概念 帧中继映射 Inverse-ARP的操作 帧中继配置 帧中继简介 分组交换广域网接入方式的一个代表,分组交换是以分组的形式在广域 ...

  3. CNN卷积神经网络的构建

    1.卷积神经网络由输入层,卷积层,激活函数,池化层,全连接层组成. input(输入层)--conv(卷积层)--relu(激活函数)--pool(池化层)--fc(全连接层) 2.卷积层: 主要用来 ...

  4. es6 babel 安装以及使用

    1,安装好node(需要使用npm包管理工具) 2,在本地项目路径下npm init,格式化成功后会在项目下生成一个配置文件package.json 3,本地安装bable npm install - ...

  5. [TimLinux] CSS pre超长自动换行

    使用css样式值: pre { white-space: pre-wrap; word-wrap: break-word; }

  6. LightOJ 1253 Misere NIM(反NIM博弈)

    Alice and Bob are playing game of Misère Nim. Misère Nim is a game playing on k piles of stones, eac ...

  7. HDU-1274

    在纺织CAD系统开发过程中,经常会遇到纱线排列的问题.  该问题的描述是这样的:常用纱线的品种一般不会超过25种,所以分别可以用小写字母表示不同的纱线,例如:abc表示三根纱线的排列:重复可以用数字和 ...

  8. HDU-1027Ignatius and princess II

    Now our hero finds the door to the BEelzebub feng5166. He opens the door and finds feng5166 is about ...

  9. 洛谷 题解 P1615 【西游记公司】

    我的程序只有1行... return scanf("%d:%d:%d\n%d:%d:%d\n%d", &a, &b, &c, &x, &y, ...

  10. matlab画二叉树

    用matlab画如下图的二叉树. 先按树的先序遍历把结点编号,如下图所示. treeplot函数的序列用如下方法得到.从根结点开始先序遍历,依次写下父结点的编号,设根结点的父结点为0.按先序遍历,根结 ...