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

后端调优——分布式锁选型——入门

文章目录

    • 引言
    • 正文
      • 分布式锁的定义
      • 分布式锁的具体应用场景
      • 如何实现分布式锁
        • 主动轮询型分布式锁
          • 实现思路
          • 一、MySQL分布式锁
          • 二、Redis分布式锁
        • 监听回调型分布式锁
          • Etcd分布式锁
          • Zookeeper分布式锁
      • 锁的对比
    • 总结

引言

  • 最近面试,一直被问到分布式锁,然后仅仅只知道redis,了解的不够深刻,这里做一个深入的总结

正文

分布式锁的定义

  • 在Java多线程编程中,使用Synchronized来实现多个线程之间有序地访问共享资源。相似地定义,分布式锁针对多个机器而言的,控制他们有序访问共享的资源节点。

  • 一般是通过第三方组件,控制多个机器有序访问,常见的有

    • MySQL
    • Redis
    • Etcd
    • Zookeeper
  • 基于redis中的分布式锁的命令“setnx key value px expire_time”,分布式锁具有如下性质

    • 独占性:同一把锁,某一个时刻只能被一个机器占用。
    • 健壮性:不会轻易死锁,如果持有锁的机器偶然死机了,也能够通过过期时间进行兜底,顺利解锁,其他机器持有锁
    • 对称性:谁加锁,谁解锁,就像redis中的value是每一个线程的uuid一样。

分布式锁的具体应用场景

多任务调度场景

  • 多个任务调度器在不同节点上运行,从任务队列中取出任务执行
    • 分布式锁能够保证每一个任务都只会被调用一次

电子商务场景

  • 电子商务系统中,创建订单的操作会涉及检查库存、支付服务以及物流服务等多个阶段,通过分布式锁,保证这些服务按照指定的顺序执行,保证数据的一致性。

如何实现分布式锁

  • 分布式锁的实现模型主要分为两种
    • 主动轮询型
      • 取锁方会持续地向分布式锁服务发出获取锁的动作,如果锁已经被占用了,会不断发起轮询请求,直到取到锁为主
      • 常见类型
        • MySQL、Redis
    • 监听回调型
      • 在取锁方发现锁已经被其他对象占用时,会创建watcher(监听器)来订阅锁的释放事件,随后不主动获取锁
      • 当锁被释放的时候,取锁方能通过之前创建的watcher监听到这一变化,发起竞争锁的尝试动作。
      • 常见类型
        • Etcd、Zookeeper
主动轮询型分布式锁
实现思路

使用一个数据变量来表示锁,redis中类似一个String对象,具体流程如下

  • 创建一个变量lock表示一把锁,lock是锁的名称,lock的内容是持有锁的具体对象

    • 加锁,创建lock对象,并将自身的标识写入到lock中
    • 解锁,删除lock对象
    • 轮询锁,如果锁已经被其他人获取,就持续性轮询,判定这个变量还存不存在,直到自己持有锁
  • 常见的有两种方式

    • redis
    • MySQL
一、MySQL分布式锁
  • MySQL加入数据时,需要满足唯一性约束,如果满足插入成功,不满足插入不成功。基于此,可以尝试将限定访问的方法设置为具有唯一性约束的数据

    • 加锁:插入名称为方法名的记录
    • 解锁:删除名称为方法名的记录
    • 轮询锁: 检查对应字段是否存在
  • 具体实现方法如下

CREATE TABLE 'LOCK_INFO'('ID' INT(11) UNSINGNED NOT NULL AUTO_INCREMENT,'METHOD_NAME' VARCHAR(64) NOT NULL ,PRIMARY KEY('ID'),UNIQUE KEY 'METHOD_NAME'   // 这个最关键,指明访问的互斥资源对应字段是独一无二的
)
  • 竞争锁的方式如下
INSERT INTO LOCK_INFO (NAME) VALUES('LOCKMETHODS');

缺点

  • 运行缓慢

    • 数据库操作的是磁盘,是通过磁盘IO来实现数据的读写,在高并发的情况下,运行缓慢
  • 容易死锁

    • 并不能像redis一样,有px,可以给每一个锁设置一个过期时间进行兜底。如果持有锁的线程挂掉了,没有删除数据库中的锁记录,就会导致死锁
  • 单点依赖性

    • 数据库是单点,非常依赖数据库的可用性

基本上不用,运行慢而且死锁难以解决,还是会用基于内存存储的组件来实现分布式锁

二、Redis分布式锁
  • 不同于MySQL,redi是基于内存的存储系统,轻便高效,并且redis是使用单线程模型来完成主要工作的。
  • redis的setnx命令
    • ex:可以设置过期时间,以及自身也有过期键删除策略,所以能够有效避免死锁问题
    • nx:nx仅仅是目标不存在时,才会设置对象,所以轻松实现分布式锁

具体实现流程

  • 每一把锁,使用同一数据来标识,key就是锁的名字
  • 加锁:向redis中插入一条key为锁的名字的数据,表示加锁成功
  • 解锁:删除名称为key的记录,表示解锁成功
  • 轮询:在加锁的时候,发现数据已经存在,就轮询等待,直到持有锁的一方释放锁
    • 正常情况下,会间隔一段时间在尝试获取锁

健壮性的实现——锁能够顺利传下去

  • 工作站崩溃,无限期持有锁

    • 使用ex指令,超过了过期时间,会自动释放锁,防止线程因为持有锁而陷入死锁状态
  • 工作没干完就过期了

    • 看门狗机制
      • 单独创建一个线程,定时向redis进行续期操作,防止业务完成之前,锁就过期了
      • 某一个线程长期持有锁,会让其他工作站拿不到锁

对称性的实现——谁加锁谁释放

  • Lua脚本
    • 使用Lua脚本保证,判断锁的归属权 + 删除锁 操作的原子性
      在这里插入图片描述

高可用保障——RedLock

  • redis 本身单点执行的,为了应对单点故障,redis支持主从复制,但是redis的主从复制是异步的,这就会导致锁的独占性问题。

    • 多个对象同时获得一把锁情况
      • 对象A在Master中获得了lock锁,但在之后Master立刻崩溃,但是Slave还没来的及将锁同步过去
      • slave提升为Master,但是其中并没有对象A关于lock锁的获取情况,所以对象B在申请lock,也会成功
      • 使得对象A和对象B同时获得了lock
  • RedLock多个节点的锁

    • 客户端会和多个独立的Redis实例依次请求加锁,只要获得半数一样的锁,就算是加锁成功,这样不用担心崩溃问题了。
    • 只要多数redis节点正常工作,分布式锁就能正常工作,提升分布式锁的可靠性。
  • 锁获取失败

    • 锁获取失败之后,会释放已经获得的部分锁,并等待一段随机时间后,在重试获得锁
监听回调型分布式锁
  • 不用轮询的,相当于给管理员一个通知方式,有锁可以竞争,就直接通知需要竞争锁的对象来竞争锁。
  • 加锁解锁和之前轮询的差不多,唯一的区别就是不用一直轮询,具体流程如下
    • 定义锁:一把锁,用一个数据来标识
    • 加锁:在存储组件里面插入一条数据,这条数据之前不存在,插入成功,加锁成功
    • 解锁:将该条数据从存储组件中删除的行为是解锁操作

最大的区别

  • 加锁失败监听
    • 锁的竞争者回去监听锁的删除事件
    • 当发生锁的删除事件之后,锁的竞争者会继续尝试获取锁。

常见应用

  • Etcd分布式锁
  • ZooKeeper
Etcd分布式锁

Etcd是一种key-value的基于内存的分布式存储仓库,其实分布式锁的方式如下。

健壮性——锁能够顺利流转

  • 租约机制

    • 可以为保存锁的key-value设置租约,即使持有锁的对象出现故障,也能够到期自动释放锁,删除键值对
    • 支持续约,相当于redis中专门实现的一个看门狗续期线程
  • watch机制

    • 支持watch某个固定的key或者watch一个范围的key
    • 一旦某一个key或者范围发生变化,客户端会收到通知

总结

  • Etcd是基于Raft协议实现的高可靠、强一致性的存储组件,正常情况下不会像Redis主从异步复制一样导致出现所数据丢失的情况
  • Etcd是监听回调型分布式锁,基于Watch机制,能够感知锁的释放,再去拿锁,不会像redis一样轮询
Zookeeper分布式锁
  • 用于提供分布式引用程序协调服务的组件
  • Zookeeper是一种树型结构,具有固定的根节点/,只能在根节点下创建子节点,并在子节点下继续创建节点,只能用绝对路径查询Zookeeper节点。
  • 总共有4种类型的节点
    • 持久节点:
      • 一直存在于Zookeeper中的节点,默认的接待你
    • 持久顺序节点:
      • 创建节点时,按照创建节点的顺序对节点进行编号
    • 临时节点(分布式锁实现)
      • 客户端和ZooKeeper连接时临时创建的节点,客户端断开俩节后,进程创建的临时节点就会被删除
      • 依赖定期的心跳检测来实现
    • 临时顺序节点
      • 按时间顺序编号创建的临时节点

在这里插入图片描述

具体实现流程

  • 加锁

    • 创建临时顺序节点,不用担心续期的问题,会有心跳检测,直到客户端完成任务才会断开
    • 当客户机宕机后,临时节点就会随之消亡
  • 解锁

    • 客户机完成任务后,主动断开链接,临时节点会消亡。
  • 监听

    • 监听上一个节点的删除事件

锁的对比

在这里插入图片描述

总结

  • 这里再说分布式锁的选型的时候,就可以大概从性能和可靠性的角度介绍一下,然后在选择redis,因为我的项目确实对于性能的要求更高,对于可靠性的要求并不高,而且占据任务这个唯一需要分布式锁控制访问的接口,访问时间也很快,不会出现执行时间过长,分布式锁过期的情况。
  • 两个角度
    • 业务本身:执行时间很短、对于安全性和可靠性的要求并不高(任务本身是幂等的),对于性能要求的高,
    • 分布式锁的特性:redis是上述四种锁中性能最高的,而且比较熟悉

相关文章:

后端调优——分布式锁选型——入门

文章目录 引言正文分布式锁的定义分布式锁的具体应用场景如何实现分布式锁主动轮询型分布式锁实现思路一、MySQL分布式锁二、Redis分布式锁 监听回调型分布式锁Etcd分布式锁Zookeeper分布式锁 锁的对比 总结 引言 最近面试,一直被问到分布式锁,然后仅仅…...

k8s集群管理 Pod管理命令

k8s集群管理命令 信息查询命令 子命令说明help用于查看命令及子命令的帮助信息cluster-info显示集群的相关配置信息api-resources查看当前服务器上所有的资源对象api-versions查看当前服务器上所有资源对象的版本config管理当前节点上的认证信息 资源对象概述 Pod概述 Pod 管…...

Java 并发(二)—— AQS原理

AQS,全名AbstractQueuedSynchronizer。 抽象队列同步器定义多线程访问共享资源的同步模板,解决了实现自定义同步器时涉及的大量细节问题,简化开发两种同步状态:独占、共享核心组件:State变量、CLH变体队列、获取 / 释…...

Maven插件:exec-maven-plugin-代码执行或者直接输出内置变量信息

文章目录 概述使用应用自行实现记录项目打包插件 概述 官网&#xff1a; https://www.mojohaus.org/exec-maven-plugin/usage.html   依赖&#xff1a; https://mvnrepository.com/artifact/org.codehaus.mojo/exec-maven-plugin 使用 <plugin><groupId>org.codeh…...

https://ffmpeg.org/

https://ffmpeg.org/ https://www.gyan.dev/ffmpeg/builds/ https://github.com/BtbN/FFmpeg-Builds/releases F:\Document_ffmpeg F:\Document_ffmpeg\ffmpeg-master-latest-win64-gpl-shared\bin...

linux 源码部署polardb-x 错误汇总

前言 在linux 源码部署polardb-x 遇到不少错误&#xff0c;特在此做个汇总。 问题列表 CN 启动报错 Failed to init new TCP 详细错误如下 Caused by: Failed to init new TCP. XClientPool to my_polarx#267b21d8127.0.0.1:33660 now 0 TCP(0 aging), 0 sessions(0 runni…...

vscode用快捷键一键生成vue模板

项目中有些代码模块是固定的&#xff0c;如下面的代码所示&#xff0c;为了不重复写这些相同的代码&#xff0c;我们可以使用快键键一键生成模板。 流程&#xff1a; 中文&#xff1a;首选项-> 用户代码片段 -> 输入框中输入vue,找到vue.json文件&#xff08;没有vue.j…...

ARM 架构硬件新趋势:嵌入式领域的未来

目录 目录 一、ARM 架构概述 二、新趋势一&#xff1a;AI 加速器集成 三、新趋势二&#xff1a;更高效的电源管理 四、新趋势三&#xff1a;安全性增强 五、结语 随着物联网 (IoT) 和边缘计算的发展&#xff0c;ARM 架构在嵌入式系统中的应用越来越广泛。从智能手机到智能…...

星戈瑞-二油酰磷脂酰乙醇胺标记荧光素 DOPE-FITC

DOPE-FITC&#xff0c;全称为1,2-dioleoyl-sn-glycero-3-phosphoethanolamine-N-FITC&#xff0c;是一种结合了二油酰磷脂酰乙醇胺&#xff08;DOPE&#xff09;与荧光素异硫氰酸酯&#xff08;FITC&#xff09;的复合标记物。以其独特的磷脂结构和强烈的绿色荧光特性&#xff…...

堆的实现(偷懒版)

&#x1f339;个人主页&#x1f339;&#xff1a;喜欢草莓熊的bear &#x1f339;专栏&#x1f339;&#xff1a;数据结构 目录 前言 一、堆的实现 1.1 堆的向下调整算法 思路&#xff1a; 1.2 堆的向上调整算法 1.3 堆的创建 1.4 堆的复杂度计算 向下调整建堆的复杂度…...

一键启动,智能分拣:3D视觉系统赋能多SKU纸箱高效混拆作业

在快速发展的电商时代&#xff0c;仓储物流面临着前所未有的挑战。尤其是面对成千上万种不同的纸箱&#xff0c;如何实现快速、准确、高效的混拆作业&#xff0c;成为了众多企业亟待解决的问题。幸运的是&#xff0c;随着科技的进步&#xff0c;3D视觉系统正逐步成为这一领域的…...

unity草体渲染方案 GPU Instaning

有一天看项目里的FrameDebug发现在森林系的场景里草体的drawcall差不多有100多 主要是因为灯光贴图&#xff0c;位置等不一样导致的打断合批&#xff0c;导致一个批次只能渲染10个左右的草体 之前有了解过unity有接口&#xff08;Graphics.DrawMeshInstanced&#xff09;可以把…...

最近在西安召开的学术会议:EI检索超快,信息系统与计算技术领域!

第十二届信息系统与计算技术国际会议&#xff08;ISCTech 2024&#xff09;将于2024年11月8日-11月11日在中国西安盛大举行&#xff0c;由长沙理工大学主办&#xff0c;同济大学、西北工业大学联合协办。会议聚焦信息系统与计算技术等相关研究领域&#xff0c;广泛邀请国内外知…...

sRGB和伽马矫正

sRGB和伽马矫正 1. sRGB的含义&#xff1a; sRGB是一种色彩空间&#xff0c;全称为“标准红色-绿色-蓝色”&#xff08;standard Red Green Blue&#xff09;。它由惠普和微软在1996年共同开发&#xff0c;用于确保不同设备上色彩的一致性。 在sRGB中&#xff0c;“s”代表“…...

Summer School science communication project--Laptop Selection Suggestion

目录 Introduction Audiance Usage CPU What is a central processing unit (CPU) Notable makers of CPUs GPU Graphics Card: GPU The classifications of graphics cards The brands of graphics cards Dedicated Graphics Cards GeForce MX Series: GeForc…...

网络编程概念详解模拟回显客户端服务器

目录 1.网络中重要的概念 1&#xff09;IP地址&#xff1a; 2&#xff09;端口号&#xff1a; 3&#xff09;协议 协议分层 OSI七层模型(教科书) TCP/IP五层模型 封装和分用 网络套接字 面试题&#xff1a;TCP/UDP的区别&#xff1f; UDP数据报套接字编程 模拟一个回…...

代码随想录第二十四天|动态规划(8)

目录 LeetCode 300. 最长递增子序列 LeetCode 674. 最长连续递增序列 LeetCode 718. 最长重复子数组 LeetCode 1143. 最长公共子序列 LeetCode 1035. 不相交的钱 LeetCode 53. 最大子序和 LeetCode 392. 判断子序列 总结 LeetCode 300. 最长递增子序列 题目链接&#…...

编程-设计模式 3:单例模式

设计模式 3&#xff1a;单例模式 定义与目的 定义&#xff1a;单例模式确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问该实例。目的&#xff1a;这种模式通常用于那些需要频繁访问且只需一个实例的对象&#xff0c;例如配置管理器、日志记录器等。 实现示例…...

Kaniko 构建 Docker 镜像

Kaniko 主要用于构建 Docker 镜像&#xff0c;而不是运行程序。它的主要用途是从 Dockerfile 构建容器镜像&#xff0c;但它并不负责运行容器或程序。以下是 Kaniko 的主要功能和局限性&#xff1a; 主要功能 构建镜像&#xff1a;Kaniko 从 Dockerfile 构建容器镜像。它通过…...

Javascript常见算法(每日两个)

合并两个有序链表 在JavaScript中&#xff0c;合并两个有序链表通常指的是将两个已经按照某种顺序&#xff08;如升序或降序&#xff09;排列的链表合并成一个新的有序链表。由于JavaScript本身不直接支持链表数据结构&#xff0c;我们通常会用对象或数组来模拟链表的行为。但…...

[RDK X5] MJPG编解码开发实战:从官方API到OpenWanderary库的C++/Python实现

业余时间一直在基于RDK X5搞一些小研究&#xff0c;需要基于高分辨率图像检测目标。实际落地时&#xff0c;在图像采集上遇到了个大坑。首先&#xff0c;考虑到可行性&#xff0c;我挑选了一个性价比最高的百元内摄像头&#xff0c;已确定可以在X5上使用&#xff0c;接下来就开…...

Azure 虚拟机端口资源:专用 IP 和公共 IP Azure Machine Learning 计算实例BUG

## 报错无解 找不到Azure ML 计算实例关联的 NSG .env 文件和 ufw status&#xff1a; .env 文件中 EXPOSE_NGINX_PORT8080 是正确的&#xff0c;它告诉 docker-compose.yaml 将 Nginx 暴露在宿主机的 8080 端口。 sudo ufw status 显示 Status: inactive&#xff0c;意味着宿…...

快捷键的记录

下面对应的ATL数字 ATL4 显示编译输出 CTRL B 编译 CTRLR 运行exe 菜单栏 ALTF ALTE ALTB ALTD ALTH...

设计模式基础概念(行为模式):模板方法模式 (Template Method)

概述 模板方法模式是一种行为设计模式&#xff0c; 它在超类中定义了一个算法的框架&#xff0c; 允许子类在不修改结构的情况下重写算法的特定步骤。 是基于继承的代码复用的基本技术&#xff0c;模板方法模式的类结构图中&#xff0c;只有继承关系。 需要开发抽象类和具体子…...

simulink这边重新第二次仿真时,直接UE5崩溃,然后simulink没有响应

提问 &#xff1a; simulink这边重新第二次仿真时&#xff0c;直接UE5崩溃&#xff0c;然后simulink没有响应 simulink和UE5仿真的时候&#xff0c;simulink这边先停止仿真&#xff08;也就是官方要求的顺序——注意&#xff1a;如果先在UE5那边停止仿真&#xff0c;如果UE5这…...

限流算法java实现

参考教程&#xff1a;2小时吃透4种分布式限流算法 1.计数器限流 public class CounterLimiter {// 开始时间private static long startTime System.currentTimeMillis();// 时间间隔&#xff0c;单位为msprivate long interval 1000L;// 限制访问次数private int limitCount…...

程序代码篇---Python串口

在 Python 里&#xff0c;serial库&#xff08;一般指pyserial&#xff09;是串口通信的常用工具。下面为你介绍其常用的读取和发送操作函数及使用示例&#xff1a; 1. 初始化串口 要进行串口通信&#xff0c;首先得对串口对象进行初始化&#xff0c;代码如下&#xff1a; i…...

3. 简述node.js特性与底层原理

&#x1f63a;&#x1f63a;&#x1f63a; 一、Node.js 底层原理&#xff08;简化版&#xff09; Node.js 是一个 基于 Chrome V8 引擎构建的 JavaScript 运行时&#xff0c;底层核心由几部分组成&#xff1a; 组成部分简要说明 1.V8 引擎 将 JS 编译成机器码执行&#xff0…...

基于JWT+SpringSecurity整合一个单点认证授权机制

基于 JWT Spring Security 的授权认证机制&#xff0c;在整体架构设计上体现了高度的安全性与灵活性。其在整合框架中的应用&#xff0c;充分展示了模块化、可扩展性和高效鉴权的设计理念&#xff0c;为开发者提供了一种值得借鉴的安全架构模式。 1.SpringSecurity概念理解 …...

深入理解二叉搜索树:原理到实践

1.二叉搜索树的概念 ⼆叉搜索树⼜称⼆叉排序树&#xff0c;它或者是⼀棵空树&#xff0c;或者是具有以下性质的⼆叉树 若它的左树不为空&#xff0c;则左子树上所有节点的值都小于或等于根节点的值。若它的右树不为空&#xff0c;则右子树上所有节点的值都大于或等于根节点的…...