自学八股:分布式锁基础

前置知识

分布式系统,一个后端服务会与多个客户端进行连接,所以会有负载均衡,多线程和异步这些情况 由于SpringBoot项目中内置Tomcat,所以处理一般都是多线程的

主要在项目的任务领取功能的部分使用了分布式锁

  • 在分布式系统中,分布式锁 是一种用于协调多个进程或线程对共享资源访问的机制。它主要用于解决在高并发场景下对共享资源的竞争问题,确保在任意时刻只有一个客户端可以操作共享资源。
  • 在分布式系统中,某些任务可能需要确保在任意时刻只有一个实例在运行。分布式锁可以防止多个实例同时执行相同的任务。
  • 在分布式系统中,多个客户端可能会同时对数据库或缓存进行写操作。如果没有适当的同步机制,可能会导致数据不一致。 在某些场景下,需要确保在读取和写入共享资源时的原子性。分布式锁可以防止多个客户端同时进行读写操作,从而保证数据的一致性。
  • 在分布式系统中,多个客户端可能会同时对共享数据进行操作。如果没有适当的同步机制,可能会导致数据竞争,从而导致数据不一致。

这个项目为什么要使用分布式锁:防止任务超领;

ps: 要区分线程锁和分布式锁,像java中实现的synchronized和Lock,线程锁本质是基于线程之间的共享内存实现的

实际使用

分布式锁的核心就是大家共用一把锁,这样就可以锁住线程,不让线程进行,让程序串行化执行,在实际中通过Mysql,Redis,Zookpeer都可以,但是在项目中主要使用的是用Redis实现分布式锁,所以这里主要探讨利用Redis实现分布式锁

1,基于SETNX实现分布式锁

获取锁:

  • 互斥 :每次只能有一个线程获得锁
  • 非阻塞:尝试一次,成功返回true,失败返回false 释放锁:
  • 手动释放
  • 超时释放
  • 保证故障的时候依然可以释放锁,避免出现死锁

这个实现的锁可以基于lua脚本进行进一步的改进,保证锁的原子性,并负担解锁的任务

2,基于RedLcok实现分布式锁

假设有两个服务A、B都希望获得锁,有一个包含了5个redis master的Redis Cluster,执行过程大致如下:

  1. 客户端获取当前时间戳,单位: 毫秒
  2. 服务A轮寻每个master节点,尝试创建锁。(这里锁的过期时间比较短,一般就几十毫秒) RedLock算法会尝试在大多数节点上分别创建锁,假如节点总数为n,那么大多数节点指的是n/2+1。
  3. 客户端计算成功建立完锁的时间,如果建锁时间小于超时时间,就可以判定锁创建成功。如果锁创建失败,则依次(遍历master节点)删除锁。
  4. 只要有其它服务创建过分布式锁,那么当前服务就必须轮寻尝试获取锁。

3,基于Redission实现

优势:

  1. redission的所有指令都是基于lua脚本实现,保证了操作的原子性
  2. redission设置了watchdog看门狗,看门狗的逻辑保证了没有死锁发生
  3. redisson支持RedLock的实现方式

如何使用

  1. 线程去获取锁,获取成功: 执行lua脚本,保存数据到redis数据库。
  2. 线程去获取锁,获取失败: 订阅了解锁消息,然后再尝试获取锁,获取成功后,执行lua脚本,保存数据到redis数据库

互斥,可重入,watch dog后面再具体说

总结:

这就是一些分布式锁的基础知识,之前面试的时候,面试官问这里问的非常多,但是当时没太懂,甚至把分布式锁说成了线程锁(哈哈)

相关推荐
期待のcode19 小时前
MyBatisX插件
java·数据库·后端·mybatis·springboot
华仔啊1 天前
这 10 个 MySQL 高级用法,让你的代码又快又好看
后端·mysql
码事漫谈1 天前
国产时序数据库崛起:金仓凭什么在复杂场景中碾压InfluxDB
后端
上进小菜猪1 天前
当时序数据不再“只是时间”:金仓数据库如何在复杂场景中拉开与 InfluxDB 的差距
后端
盖世英雄酱581361 天前
springboot 项目 从jdk 8 升级到jdk21 会面临哪些问题
java·后端
程序猿DD1 天前
JUnit 5 中的 @ClassTemplate 实战指南
java·后端
Victor3561 天前
Netty(14)如何处理Netty中的异常和错误?
后端
Victor3561 天前
Netty(13)Netty中的事件和回调机制
后端
码事漫谈1 天前
VS Code 1.107 更新:多智能体协同与开发体验升级
后端