redis分布式锁的实现及问题分析
来源:互联网 发布:双十一淘宝津贴怎么用 编辑:程序博客网 时间:2024/06/11 11:20
Implementing a distributed lock manager with Redis.使用redis实现一个分布式锁的管理
当我们需要用不同的进程或者线程处理同一个资源的时候,锁就显得比较重要了。redis的分布式锁叫做redlock
接下来我们看一下如何用redis实现一个分布式的锁管理。
在 github上有一些使用redis分布式锁的官方的例子。https://github.com/ronnylt/redlock-php
以php来举例:
定义三台redis服务器:
$servers = [
['127.0.0.1', 6379, 0.01],
['127.0.0.1', 6389, 0.01],
['127.0.0.1', 6399, 0.01],];
创建一个锁管理:
$redLock = new RedLock($servers);
然后锁住一个键,并且设置锁住的时间。时间是以毫秒为单位的。
$lock = $redLock->lock('my_resource_name', 1000);
如果失败返回false,成功则会返回以下数据:
Array(
[validity] => 9897.3020019531
[resource] => my_resource_name
[token] => 53771bfa1e775)
我一开始看到这个的时候想到的是: 为什么要用这种形式去上锁,在我们平常的工作中,直接使用set命令
给一个key设置一个值和过期时间不久可以上锁了嘛? 我们来看看官方是如何解释的。
上锁的意义在于:这种机制在同一时间段内只允许一个请求进行操作。
举个简单的例子,比如你有3台机器要进行写操作,为了保证数据正确性,你同时只能允许一台机器进行
write操作,那么进行write操作之前必须先获取锁,获得了锁的机器可以进行操作,其他两台机器必须等待
锁的释放并获取到锁以后才能进行操作。
现在的操作系统提供了类似于flock的命令对文件进行上锁,但是如果你在多台机器上又如何操作呢?如果你需要设置处理
权限的是一个分布式的集群服务呢?
首先我们必须确立一个思想,我们必须在一个公共的地方存储一个锁。当所有的服务需要获取锁的时候去这个公共的地方获取。
这就意味着我们需要一个 “”锁系统 “”,redis是一个以内存为媒介的快速的数据库。
锁的设计:单台redis的锁实现非常简单,仅仅只是设置一个key而已,但是其中有一个问题也会导致严重的问题发
生, 我们来分析一下其中存在的陷阱:
1、客户端和redis服务端必须通过网络发生命令,这就意味着,从发送到服务端执行,其中肯定会存在一定的延迟时间。
在这段时间中redis会执行其他的命令,这就可能会让你需要获取的值发生变化。你如何保证其中只有一个程序在建立了操作这个key的连接呢?(先get再set都是一个非原子性的操作),你可以使用setnx来解决这个问题。
2、如果已经获得了锁的程序发生了崩溃,那就变成一个永远都存在的锁了,没人去取消它。这个时候我们需要设置一个过期时间来解决它。
也许我们的代码是这样:
MULTI
SETNX lock-key
PEXPIRE 10000 lock-key
PEXPIRE 10000 lock-key
EXEC
但是这又带来了另外一个问题:expire命令并不会管setnx的执行结果,不管setnx是否执行成功,expire都会执行,那是不是意味着
每个连接都会更新过期时间,key又变成了永远不会过期的键了。
上面是最 简单的办法,redis是单进程的,所以其实我们还有另外一个完美解决问题的办法,通过脚本来获取key,
你可以通过执行一个lua脚本来获取key并设置key的过期时间,redis会缓存该脚本,你可以通过eval或者evalsha来执行
脚本内容,这样就可以实现原子性的操作。并且保证key和expire都设置成功 。下面是官方提供的lua脚本:
---- Set a lock---- KEYS[1] - key-- KEYS[2] - ttl in ms-- KEYS[3] - lock contentlocal key = KEYS[1]local ttl = KEYS[2]local content = KEYS[3] local lockSet = redis.call('setnx', key, content) if lockSet == 1 then redis.call('pexpire', key, ttl)end return lockSet
这里再提供一下用node.js写的操作redis的脚本库文件,帮助我们实现分布式的锁,消息队列以及其他敏感的并发操作代码。
这个开源的nodejs脚本库叫做warlock,地址是https://github.com/thedeveloper/warlock
0 0
- redis分布式锁的实现及问题分析
- Redis分布式锁的简单实现分析
- 基于Redis实现分布式锁-Redisson使用及源码分析
- 基于Redis实现分布式锁,Redisson使用及源码分析
- 基于Redis实现分布式锁,Redisson使用及源码分析
- 基于Redis实现分布式锁,Redisson使用及源码分析
- 基于Redis实现分布式锁,Redisson使用及源码分析
- API接口非幂等性问题及使用redis实现简单的分布式锁
- redis分布式锁的实现
- redis实现的分布式锁
- redis分布式锁的实现
- 分布式锁的redis实现
- 【Redis深入】Redis分布式锁的实现
- Redis实现分布式锁原理与实现分析
- Redis实现分布式锁
- Redis 分布式锁实现
- Redis 分布式锁实现
- Redis实现分布式锁
- [课堂笔记]小白菜鸟重装系统
- android Framework层添加资源方式
- 从零开始学写HTTP服务器(四)IO复用
- python Flask学习笔记(一)
- PAT A1063
- redis分布式锁的实现及问题分析
- aChartEngine小结
- Perl知识点滴
- c::动态顺序表的简单实现
- pyqt4之sqlite数据库连接测试
- 小博老师解析Java核心技术 ——JSwing文本域和滚轴控件
- myeclipse10导入其他地方的项目时jsp报错的有效解决方法
- 防止过拟合的处理方法
- Java面向对象特点----继承