基于Redis实现分布式锁——Java版本
基于Redis实现分布式锁——Java版本
- 版本一
- 版本二
- 版本三
- Redisson
定义分布式锁接口如下:
public interface ILock {boolean tryLock(long timeoutSec);void unlock();
}
版本一
设定业务超时时间,到期自动解锁。缺点是超时时间不好估计,需要略大于业务执行的时间。当超时时间小于执行业务时间时,其他线程会拿到锁,而之前的线程执行完后又会解锁,变得混乱,导致线程安全问题。
public class SimpleRedisLock implements ILock{@Autowiredprivate StringRedisTemplate stringRedisTemplate;private String name;private static final String KEY_PREFIX = "lock:";@Overridepublic boolean tryLock(long timeoutSec) {Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, Thread.currentThread().getId() + "",timeoutSec, TimeUnit.SECONDS);return Boolean.TRUE.equals(success);}@Overridepublic void unlock() {stringRedisTemplate.delete(KEY_PREFIX + name);}
}
版本二
解锁时判断锁是否和自己假的锁标识一样,标识使用UUID+线程ID,标识一样才释放锁。每个线程都会创建一个SimpleLock,因此保证UUID不一样。
public class SimpleRedisLock implements ILock{private StringRedisTemplate stringRedisTemplate;private String name;private static final String KEY_PREFIX = "lock:";private static final String ID_PREFIX = UUID.randomUUID().toString() + "-";public SimpleRedisLock(StringRedisTemplate stringRedisTemplate, String name) {this.stringRedisTemplate = stringRedisTemplate;this.name = name;}@Overridepublic boolean tryLock(long timeoutSec) {String value = ID_PREFIX + Thread.currentThread().getId();Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, value,timeoutSec, TimeUnit.SECONDS);return Boolean.TRUE.equals(success);}@Overridepublic void unlock() {String value = ID_PREFIX + Thread.currentThread().getId();String id = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);if (value.equals(id)) {stringRedisTemplate.delete(KEY_PREFIX + name);}}
}
版本三
某个线程先判断锁是自己的,此时由于其他原因阻塞,比如Full GC,其他线程拿到锁,之前的线程再解锁,但是解的并不是自己的锁,导致线程安全问题。
需要保证这些操作的原子性。使用Lua脚本。
使用redis提供的函数call。key类型参数放入KEYS数组,其他参数放入ARGV数组,Lua中数组角标从1开始。Lua脚本如下。
if (redis.call('get', KEYS[1]) == ARGV[1]) thenreturn redis.call('del', KEYS[1])
end
return 0
Lua脚本放在resources文件夹下,在Java代码中调用StringRedisTemplate的execute方法执行Lua脚本。最后分布式锁代码为
public class SimpleRedisLock implements ILock{private StringRedisTemplate stringRedisTemplate;private String name;private static final String KEY_PREFIX = "lock:";private static final String ID_PREFIX = UUID.randomUUID().toString() + "-";private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;static {UNLOCK_SCRIPT = new DefaultRedisScript<>();UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));UNLOCK_SCRIPT.setResultType(Long.class);}public SimpleRedisLock(StringRedisTemplate stringRedisTemplate, String name) {this.stringRedisTemplate = stringRedisTemplate;this.name = name;}@Overridepublic boolean tryLock(long timeoutSec) {String value = ID_PREFIX + Thread.currentThread().getId();Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, value,timeoutSec, TimeUnit.SECONDS);return Boolean.TRUE.equals(success);}@Overridepublic void unlock() {stringRedisTemplate.execute(UNLOCK_SCRIPT,Collections.singletonList(KEY_PREFIX + name),ID_PREFIX + Thread.currentThread().getId());}
}
Redisson
上述实现的分布式锁缺点为:
1、不可重入,同一线程不能对同一把锁多次加锁。
2、不可重试。
3、超时时间不好设置,有可能超时自动释放,虽然不会有误删,但是存在其他线程重新加锁。
4、主从复制的单点问题,主节点宕机导致从节点锁还没有同步。
这些功能属于拓展功能,要么出现概率低,要么可以不需要这样的需求。
Redisson包含分布式锁的成熟实现。
1、Redisson的可重入锁实现原理:
参考ReentrantLock原理,需要存储加锁次数。因此使用Redis中的Hash数据结构。key是锁名称,field是UUID+线程id,value是加锁次数。
2、Redisson的可重试锁和超时释放实现原理:
while持续在重试时间内重试,但不是一直重试,而是消息订阅和信号量,释放了再来重试。
超时释放使用了看门狗机制,每10秒钟续期30秒,无限续期,直到调用unLock方法。
3、Redisson解决主从一致性问题的原理:
去中心化,不要主从,每个节点都需要获取锁,使用了红锁算法。N个节点需要获取N/2+1个锁才能加锁成功。使用Multilock。
缺点是增加读写。
对每个节点都使用配置类把Bean加载到容器中。
RLock lock1 = redissonClient.getLock("order");
RLock lock2 = redissonClient2.getLock("order");
RLock lock3 = redissonClient3.getLock("order");
RLock lock = redissonClient.getMultiLock(lock1, lock2, lock3);
相关文章:
基于Redis实现分布式锁——Java版本
基于Redis实现分布式锁——Java版本 版本一版本二版本三Redisson 定义分布式锁接口如下: public interface ILock {boolean tryLock(long timeoutSec);void unlock(); }版本一 设定业务超时时间,到期自动解锁。缺点是超时时间不好估计,需要…...
Qt自定义控件--提升为
为什么要自定义控件 1,有复合小控件需要组合为一个整体控件时; 2,一个复合控件需要重复使用时; 实现 自定义控件文件 新增三个文件 关联不同组的控件 关联之前的准备工作 1,在主控件选择和子控件所有控件所在控件…...
Lua 基础 01 入门
Lua 基础相关知识 第一期 注释 -- 单行注释--[[多行注释 --]]-- 多加一个横杠符号就能重新启用注释内的代码 ---[[print("Lua") --]]数据类型 Lua 是动态类型语言,变量不需要类型定义,只需要为变量赋值。 Lua 有 8 种基本类型:…...
远程连接阿里云ECS
说明:ECS(阿里云服务器)可选择的系统镜像如下: 本文介绍基于Windows系统,对CentOS、Ubuntu、Windows这三个操作系统的连接方式,以及连接工具Windterm的使用。 CentOS & Windterm CentOS是我使用时间最…...
【C++】多态(上)超详细
封装,继承,多态不只是C的三大特性,而是面向对象编程的三大特性。 什么是多态: 不同的对象做同一件事情,结果会出现多种形态。 1.满足多态的几个条件 1.父子类完成虚函数重写(需要满足三同:函…...
【Git】 Git分支操作指南
隐形的纪念躲在心里面 也许吧 也许不会再见 阴天或晴天 一天又一年 风它在对我说莫忘这一切 🎵 蔡淳佳《隐形纪念》 Git是一种非常强大的分布式版本控制系统,允许用户在开发过程中创建不同的分支(branch)来分…...
智慧文旅赋能旅游服务升级:以科技创新驱动行业变革,打造智慧化、个性化、高效化的旅游新体验,满足游客日益增长的多元化需求
目录 一、引言 二、智慧文旅的概念与内涵 三、智慧文旅在旅游服务升级中的应用 1、智慧旅游服务平台建设 2、智慧景区管理 3、智慧旅游营销 四、智慧文旅推动旅游行业变革的案例分析 案例一:某智慧旅游城市建设项目 案例二:某景区智慧化改造项目…...
AtCoder Beginner Contest 310 E题 NAND repeatedly
E题:NAND repeatedly 标签:动态规划题意:给定一个长度为 n n n的 01 01 01字符串 A i A_i Ai,给定规则: 0 ⊼ 0 1 , 0 ⊼ 1 1 , 1 ⊼ 0 1 , 1 ⊼ 1 0 0⊼01,0⊼11,1⊼01,1⊼10 0⊼01,0⊼11,1⊼01,1⊼10。 求 ∑…...
一款简易的免费抽奖软件
一、介绍 这款抽奖软件设计简洁,操作便捷。用户可以轻松将参与名单通过EXCEL文件导入至程序中,并可根据需要设定各类奖品和对应的中奖人数。在选定了奖品后,用户只需点击“开始”按钮,随后再按下“暂停”按钮,软件便会…...
Kubernetes 监控管理
目录 1. Metrics Server2. Prometheus & Grafana3. cAdvisor4. 日志收集5. 告警与通知6. 最佳实践 Kubernetes 监控管理是确保集群稳定运行和应用服务质量的关键环节。它涉及收集、聚合、分析集群及其上运行的应用程序的各种指标和日志数据。 1. Metrics Server 作用&…...
哈希表第6/9题--四数相加II
题目描述: 给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 < i, j, k, l < nnums1[i] nums2[j] nums3[k] nums4[l] 0 示例 1: 输入&…...
使用JavaScript将富文本HTML转换为纯文本
在Web开发中,我们经常需要处理HTML内容,但有时为了特定的目的,比如文本处理、搜索或显示在非HTML环境中,我们可能希望将富文本HTML转换为纯文本。这里,我们将探讨如何使用JavaScript来实现这一功能。 为什么要将HTML转…...
2024-05-13 问AI: 介绍一下 google wavenet 声码器
文心一言 Google的WaveNet声码器是一个深度学习模型,用于生成高质量的音频信号,特别是人类语音。与传统的声码器相比,WaveNet可以生成更加自然和流畅的音频,因为它直接模拟了原始音频信号的波形生成过程。 WaveNet的核心思想是使…...
当代 Qt 正确的 安装方法 及 多版本切换
此文写于 20240511 首先去网站Index of /official_releases/online_installers下载一个安装器 安装器有什么用? 可以浏览安装版本 安装组件 安装器版本越能 能装的东西越多 现在只能选Qt5 和 Qt6 至于你公司用的Qt4 我也没招 见招时再拆招 安装器 默认国外源 可以换国内…...
matlab使用教程(70)—修改坐标区属性
1.控制坐标轴长度比率和数据单位长度 您可以控制 x 轴、y 轴和 z 轴的相对长度(图框纵横比),也可以控制一个数据单位沿每个轴的相对长度(数据纵横比)。 1.1图框纵横比 图框纵横比是 x 轴、y 轴和 z 轴的相对长度。默认…...
手撕C语言题典——反转链表
目录 前言 一.思路 1)创建新链表 2)创建三个指针 二.代码实现 搭配食用更佳哦~~ 数据结构之单单单——链表-CSDN博客 数据结构之单链表的基本操作-CSDN博客 前面学了单链表的相关知识,我们来尝试做一下关于顺序表的经典算法题~ 前言 反转…...
用lobehub打造一个永久免费的AI个人助理
Lobe Chat是一个开源的高性能聊天机器人框架,它被设计来帮助用户轻松创建和部署自己的聊天机器人。这个框架支持多种智能功能,比如语音合成(就是让机器人能说话),还能理解和处理多种类型的信息,不仅限于文字…...
Linux网络编程】传输层中的TCP和UDP(UDP篇)
【Linux网络编程】传输层中的TCP和UDP(UDP篇) 目录 【Linux网络编程】传输层中的TCP和UDP(UDP篇)传输层再谈端口端口号范围划分认识知名端口号netstatiostatpidofxargs UDP协议UDP协议端格式UDP的特点面向数据报UDP的缓冲数据UDP使…...
Ciphey无法安装的解决办法
安装过程纯属自己实践,满满干货 困扰我几天的问题终于解决了 我看着教程在window上安装 python3.8/python3.9/python3.10无论如何都安装不上, 在win10虚拟机仍然安装不上 可能是我电脑环境问题 解决办法: 在kali中安装,但是…...
交互之舞:Processing中的用户互动与响应设计
前言: 🌟在前两篇文章中,我们已经学会了如何绘制静态图形和创建动态动画。今天,我们将迈入一个新的领域——交互设计。在Processing中,用户互动是创造沉浸式体验的关键。让我们一起探索如何让用户与你的艺术作品互动&…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
