IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> redis 分布式锁常见问题 -> 正文阅读

[大数据]redis 分布式锁常见问题

上篇博客我简答介绍了 redis 常见加解锁的操作,本篇我计划整理出其中可能导致的问题:

一般情况下 redis 分布式锁都是这样使用的:

// 加锁操作
cacheService.lock(key , timeout);
// 业务逻辑
xxx
// 解锁操作
cacheService.unlock();

绝大多数情况下都没有问题,但可能存在如下情况:业务逻辑执行时间过长,锁自动失效了。如果锁失效,就有可能导致并发问题

一般情况下都是通过设置 timeout 值大于业务逻辑执行时间来解决,但总得来说这不是一个长久之计,因为随着业务逻辑的扩张,业务逻辑执行的速度可能随着业务数据的增多而变慢,如果一直动态调整 timeout 值的话,每次上线改一个参数,实际是大多数人不愿意看到的。

下面我列举出几种常见的解决方案:

1、timeout 设置为 -1,直接不过期不就行了,只有执行完业务逻辑,主动解锁下一个实例才能执行

首先这种方案肯定是不行的,假设业务逻辑执行过程中出现异常,没有执行解锁操作怎么办,那岂不是说其它实例永远无法获取分布式锁。此时你可能想说通过 finally 把解锁逻辑括起来,即使出错也解锁。那万一不是异常,而是系统直接挂了呢,finally 只能保证实例正常的情况下执行,万一本身应用已经挂了呢,此时一个实例挂了,其它等待 redis 分布式锁的实例也无法正常执行

2、通过守护线程续命,如果发现执行业务逻辑期间锁快过期了,就给它续一定的时长

使用这种方案时,实例加锁可以用当前加锁时间戳作为 value 存储,守护线程定期根据时间戳判断 value 是否快过期,如果快过期就给它延长一段时间

3、超时回滚

使用这种方案时,每个实例必须包含独立的 value 值,以该值做为分布式锁的值。每次解锁时判断当前占用锁的线程还是否自己,如果是正常执行,否则回滚,因为分布式锁执行超时

对于方案二和方案三,一旦真的出现续命或者超时回滚情况,一定要考虑 redis 过期时间是否设置的合理,适当延长时间,尽可能不要人为参与到这种加解锁的逻辑当中


最后我们再简单这块很可能存在一种异常场景:

  1. 实例 a 抢占到分布式锁,设置 value 及过期时长
  2. 此时该 key-value 保存在 redis master 节点,突然 master 节点挂了
  3. redis 集群从 slave 节点中推选出新的 master
  4. 由于异步同步的原因,新的 master 此时不包含该分布式锁 key-value
  5. 实例 b 抢占到分布式锁,设置 value 及过期时长

此时实例 a 和 实例 b 都抢占到 redis 锁,就有可能造成同步问题

实际该问题的本质是 redis 异步同步可能丢数据的问题,只是用到分布式锁这个模块比较重要,影响范围更大。此时一般有两种解决方式:

  1. RedLock 获取分布式锁
  2. Zookeeper 实现分布式锁

这里简单介绍下 RedLock 的逻辑:

  1. 获取当前时间,以毫秒为单位
  2. 客户端依次从5个毫无关系的 redis 实例请求分布式锁
  3. 通过当前时间减去步骤1的时间计算获取锁的时长,当且仅当 (N / 2 + 1)个 redis 实例获取锁成功并且获取锁的时间小于锁失效的时间才算获取锁成功

此时如果获取锁成功,锁真正有效时间等于初始有效时间(根据步骤1时间 + 过期时长算出的时间)减去真正获取到锁的时间。如果获取锁失败执行解锁逻辑

总的来说 RedLock 实施难度太大,成本高是一方面,各个 redis 实例时间还得对其,还得防止不出现重启等情况。一般很少使用,了解即可

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-09-09 11:50:45  更:2021-09-09 11:52:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:01:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码