当前位置: 首页 > news >正文

分布式锁的简单实现

1. 什么是分布式锁?

在分布式系统中,也会涉及到多个节点访问同一个公共资源的情况,和 Java 中多线程的锁不一样,由于分布式系统中涉及到多个进程多个主机,所以说 Java 中 synchronized 就不合适了。

2. 分布式锁的简单实现

思路:使用一个公共的服务器来记录加锁的状态

可以用过 Redis 来记录一个键值来表示锁的状态,当加锁的时候就设置该键值对,释放锁时就删除,不过此时就有了一个问题,如果说服务器 1 加锁之后宕机了,那么释放锁的操作就无法执行,其他服务器就不能获取锁,所以说可以通过set ex nx的方式再设置一个过期时间,键值对的设置也是有讲究的,如果设置为一个简单的 “111”,那么其他服务器也能释放锁,此时可以引入一个校验 id,比如设置为服务器编号,通过判断是否是加锁的那台服务器来释放锁。

此时还有一个问题:校验 id 时需要通过 get 操作获取值,然后通过 del 操作删除锁,这样的操作并不是原子的,那么就会导致一台服务器加锁之后,其中的两个线程进行解锁操作,当线程 A 解锁完成后,线程 B 的 del 操作前的这段时间,服务器 2 加锁之后就被释放了

可以把释放锁的逻辑写在 Lua 脚本中执行,Lua 脚本在 Redis 中的执行是原子的

3. 引入“看门狗”

上述的方案中还存在一个问题:由于把 key 的过期时间设置为了一个定值,如果设置的过小,那么任务还没执行完,锁自动释放了,这就需要引入看门狗机制,watch dog 本质上是加锁的服务器上的一个单独的线程(不是 Redis 服务器的),通过这个线程来对锁过期时间进行续约,这样就不用担心提前失效的问题了,即使服务器宕机了,watch dog 线程也就没了,无法续约,到了一定时间自然就释放锁了

4. 引入 Redlock

在实际中,Redis 一般是集群部署的,就可能出现下面这种情况:

服务器 1 向 master 节点进行加锁操作,设置 key 的过程刚刚完成,master 节点就宕机了,slave 节点升级为了新的 master 节点,但是原来主节点设置的锁并没有来得及同步过来,此时就相当于服务器 1 的锁白加了。

可以引入多组 Redis 节点,每组 Redis 节点都包含一个主节点和若干从节点,并且组和组之间的数据都是一致的,加锁的时候,按照一定的顺序,写多个 master 节点,并且设定操作的超时时间,如果超过这个时间还没有加锁成功,就认为该节点加锁失败了,根据少数服从多数的原则,如果超过一半的主节点都加锁失败,才认为本次加锁失败,解锁也是这样的操作。

http://www.lryc.cn/news/546122.html

相关文章:

  • C语言(19)----------->函数(2)
  • 动态扩缩容引发的JVM堆内存震荡:从原理到实践的GC调优指南
  • 为何在用户注销时使用 location.href 而非 Vue Router 的 router.push
  • 开源工具推荐:Uptime Kuma监控
  • 《基于Selenium的论坛系统自动化测试实战报告》
  • 深入解析SQL Server高级SQL技巧
  • 分布式中间件:环境准备
  • c# winform程序 vs2022 打包生成安装包
  • 探索Elasticsearch:文档的CRUD
  • 面试基础--Spring Boot启动流程及源码实现
  • 火语言RPA--PDF提取图片
  • 力扣977.有序数组的平方(双指针)
  • QT——文件IO
  • 分布式中间件:Redis介绍
  • 服务器和本地电脑之间如何传输文件
  • 经验分享:用一张表解决并发冲突!数据库事务锁的核心实现逻辑
  • 嵌入式学习前要了解的基础知识
  • RTC、直播、点播技术对比|腾讯云/即构/声网如何选型 — 2025 版
  • 《白帽子讲 Web 安全》之文件操作安全
  • yolov8训练模型、测试视频
  • 03.网络编程套接字(二)
  • 一周学会Flask3 Python Web开发-Flask3之表单处理WTForms安装与定义WTForms表单类
  • Git基本命令索引
  • 【论文阅读笔记】SL-YOLO(2025/1/13) | 小目标检测 | HEPAN、C2fDCB轻量化模块
  • MySQL SQL 优化专题
  • Mac上安装Pycharm
  • flask框架基础入门学习教程
  • Qt显示一个hello world
  • MySQL快速搭建主从复制
  • 力扣-动态规划-674 最长连续递增序列