基于单Redis节点的分布式锁
来源:互联网 发布:摄像头阅卷软件 编辑:程序博客网 时间:2024/06/05 11:33
场景:某个业务接口,因为做了比较复杂的数据库查询并且调用量很大,所以加了缓存,并设定缓存过期后刷新。问题是缓存过期的瞬间,大量并发请求会穿透缓存直接查询数据库,造成雪崩效应,如果有锁机制,那么就可以控制只有一个请求去更新缓存,其它的请求视情况要么等待,要么使用过期的缓存。
下面以PHPRedis 扩展为例,实现一段演示代码:
<?php$redis = new Redis();$cache = new Cache();$random = microtime(true);$ttl = 3000;$ok = $redis->set($key, $random, array('nx', 'ex' => $ttl));if($ok){ $cache->update(); if($redis->get($key) == $random) { $redis->del($key); }}$data = $cache->get();?>
问题一:为什么设置过期时间?
当一个客户端获取锁成功之后,假如它崩溃了,那么它就会一直持有这个锁,而其它客户端永远无法获得锁了,缓存就永远无法更新了。
问题二:网上不少时间设置锁的过期时间用了以下代码,存在什么问题?
<?php$redis->multi();$redis->setnx($key, $value);$redis->expire($key, $ttl);$redis->exec();?>
这段代码是有问题的:当多个请求到达时,虽然只有一个请求的setnx可以成功,但是任何一个请求的expire却都可以成功,如此就意味着即便获取不到锁,也可以刷新过期时间,如果请求比较密集的话,那么过期时间会一直被刷新,导致锁一直有效。其实Redis从2.6.12起,SET涵盖了SETEX的功能,并且SET本身已经包含了设置过期时间的功能,所以我们只需要用set设置锁的过期时间就好了。
问题三:为什么要设置一个随机数?
因为它保证了一个客户端释放的锁必须是自己持有的那个锁。设想一下,如果一个请求更新缓存的时间比锁的有效期还要长,导致在缓存更新过程中,锁就失效了,此时另一个请求会获取锁,如果不加以判断直接删除锁,就会出现误删除其它请求创建的锁的情况。
问题四:假如Redis节点宕机了该怎么办?
假如Redis节点宕机了,那么所有客户端就都无法获得锁了,服务变得不可用。为了提高可用性,我们可以给这个Redis节点挂一个Slave,当Master节点不可用的时候,系统自动切到Slave上。但由于Redis的主从复制是异步的,客户端1从Master获取了锁,此时Master宕机了,存储锁的key还没有来得及同步到Slave上,Slave升级为Master,然后客户端2从新的Master获取到了对应同一个资源的锁。针对这个问题,antirez设计了Redlock算法,基于篇幅较长,有兴趣的自己可以研究一下,加深对分布式锁的理解。
1 0
- 基于单Redis节点的分布式锁
- 基于redis单节点实现分布式锁
- 基于Redis的分布式锁
- 基于Redis的分布式锁
- 基于redis的分布式锁
- 基于redis的分布式锁
- Redis分布式缓存安装(单节点)
- 基于redis的分布式锁的实现
- 基于redis的分布式锁的实现
- 基于Redis的分布式锁实现
- 基于Redis的分布式锁实现方式
- Java实现基于Redis的分布式锁
- Java实现基于Redis的分布式锁
- Java实现基于Redis的分布式锁
- Java实现基于Redis的分布式锁
- 基于redis实现可靠的分布式锁
- 基于Redis实现简单的分布式锁
- 基于redis的分布式锁服务实现
- jzoj P1666 【AHOI2009】飞行棋
- LeetCode 16. 3Sum Closest
- 实战java高并发程序设计第一章读书笔记
- Android:怎样隐藏EditText控件的下划线
- 聊聊游戏辅助那些事上部第一篇——过掉那些讨厌的游戏保护。
- 基于单Redis节点的分布式锁
- 【算法】 多特征融合粒子滤波
- Palindrome Partitioning I,II
- 锁优化的思路和方法
- angular2系列教程(七)Injectable、Promise、Interface、使用服务
- poj 1067 石子游戏
- CSDN日报20170417 ——《程序员最好有 社保》
- Matlab卷积编码器维特比译码-通信专业课程设计
- Codeforces Round #409Div.2D. Volatile Kite(计算几何)