分布式锁详细理解及常用的实现方式

大厂面试题-请说一下你对分布式锁的理解,以及分布式锁的实现 这种方式虽然简单啊,但是要实现比较完整的分布式锁,还需要考虑重入性、锁失效机制、没抢占到锁的线程要实现阻塞等,就会比较麻烦。. 关系型数据库,可以使用唯一约束来实现锁的排他性,如果要针对某个方法加锁,就可以创建一个表包含方法名称字段,并且把。分布式锁和线程锁本质上是一样的,线程锁的生命周期是单进程多线程,分布式锁的声明周期是多进程多机器节点。2、可重入性,允许一个已经获得锁的进程,在没有释放锁之前再次重新获得锁。具备体系化的技术能力的时候,是很容易应对各种面试官的各种刁难的。 阅读详情

分布式锁

1.理解分布式锁

编程语言往往都会提供锁来保证线程并发访问共享变量,比如,Java 语言给我们提供了线程锁,开放了处理锁机制的 API,比如 Synchronized、Lock 等。当一个锁被某个线程持有的时候,另一个线程尝试去获取这个锁会失败或者阻塞,直到持有锁的线程释放了该锁。

在单台服务器内部,可以通过线程加锁的方式来同步。但是在分布式场景下就需要分布式锁来保证多实例并发安全访问共享变量。

 

分布式场景下解决并发问题,需要应用分布式锁技术。如上图所示,分布式锁的目的是保证在分布式部署的应用集群中,多个服务在请求同一个方法或者同一个业务操作的情况下,对应业务逻辑只能被一台机器上的一个线程执行,避免出现并发问题。

 

2.分布式锁应该具备的条件

  • 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行;
  • 高可用的获取锁与释放锁;
  • 高性能的获取锁与释放锁;
  • 具备可重入特性;
  • 具备锁失效机制,防止死锁;
  • 具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败。

 

 

分布式锁的常用实现方式

  实现分布式锁目前有三种流行方案,即基于关系型数据库、Redis、ZooKeeper 的方案

 

  1. 基于关系型数据库

基于关系型数据库实现分布式锁,是依赖数据库的唯一性来实现资源锁定,比如主键和唯一索引等。

 

以唯一索引为例,创建一张锁表,定义方法或者资源名、失效时间等字段,同时针对加锁的信息添加唯一索引,比如方法名,当要锁住某个方法或资源时,就在该表中插入对应方法的一条记录,插入成功表示获取了锁,想要释放锁的时候就删除这条记录。

 

下面创建一张基于数据库的分布式锁表:

CREATE TABLE `methodLock` (

`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',

`method_name` varchar(64) NOT NULL DEFAULT '' COMMENT '锁定的方法或者资源',

PRIMARY KEY (`id`),

UNIQUE KEY `uidx_method_name` (`method_name `) USING BTREE

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='对方法加锁';

当希望对某个方法加锁时,执行以下 SQL 语句:

insert into methodLock(method_name) values ('method_name');

 

在数据表定义中,我们对 method_name 做了唯一性约束,如果有多个请求同时提交到数据库的话,数据库会保证只有一个操作可以成功,那么就可以认为操作成功的那个线程获得了该方法的锁,可以执行后面的业务逻辑。

当方法执行完毕之后,想要释放锁的话,在数据库中删除对应的记录即可。

基于数据库实现分布式锁操作简单,但是并不是一个可以落地的方案,有很多地方需要优化。

缺点:

  • 这把锁强依赖数据库的可用性,数据库是一个单点,一旦数据库挂掉,会导致业务系统不可用。
  • 这把锁没有失效时间,一旦解锁操作失败,就会导致锁记录一直在数据库中,其他线程无法再获得到锁。
  • 这把锁只能是非阻塞的,因为数据的insert操作,一旦插入失败就会直接报错。没有获得锁的线程并不会进入排队队列,要想再次获得锁就要再次触发获得锁操作。
  • 这把锁是非重入的,同一个线程在没有释放锁之前无法再次获得该锁。因为数据中数据已经存在了。

 

2.基于Redis实现

 使用命令介绍:

(1)SETNX

SETNX key val:当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做,返回0。

(2)expire

expire key timeout:为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。

(3)delete

delete key:删除key

实现方法

伪代码如下:

if(setnx(key,value)==1){

    expire(key,expireTime)   //设置过期时间

     try{

        //业务处理

     }finally{

       //释放锁

       del(key)

     }

}

 

缺点:

  1. setnx和expire不是原子操作,所以存在设置了setnx 之后突然崩溃,导致锁没有设置过期时间,那么这个锁就会一直存在,无法被其他线程获取。此时可以用Redis 2.8以后支持set和expire的原子操作

          >  SET key value expireTime nx

    2. Redis集群下可能会出现竟态

        客户端 A 从 Master 节点获取锁;

       Master 节点宕机,主从复制过程中,对应锁的 key 还没有同步到 Slave 节点上;

       Slave 升级为 Master 节点,于是集群丢失了锁数据;

       其他客户端请求新的 Master 节点,获取到了对应同一个资源的锁;

      出现多个客户端同时持有同一个资源的锁,不满足锁的互斥性。

        

关于集群下如何实现分布式锁,Redis 的作者 Antirez(Salvatore Sanfilippo)提出了 Redlock 算法

Redlock 算法的流程

Redlock 算法是在单 Redis 节点基础上引入的高可用模式,Redlock 基于 N 个完全独立的 Redis 节点,一般是大于 3 的奇数个(通常情况下 N 可以设置为 5),可以基本保证集群内各个节点不会同时宕机。

 

假设当前集群有 5 个节点,运行 Redlock 算法的客户端依次执行下面各个步骤,来完成获取锁的操作:

      客户端记录当前系统时间,以毫秒为单位;

     依次尝试从 5 个 Redis 实例中,使用相同的 key 获取锁,当向 Redis 请求获取锁时,客户端应该设置一个网络连接和响应超时时间,超时时间应该小于锁的失效时间,避免因为网络故障出现的问题;

     客户端使用当前时间减去开始获取锁时间就得到了获取锁使用的时间,当且仅当从半数以上的 Redis 节点获取到锁,并且当使用的时间小于锁失效时间时,锁才算获取成功;

     如果获取到了锁,key 的真正有效时间等于有效时间减去获取锁所使用的时间,减少超时的几率;

     如果获取锁失败,客户端应该在所有的 Redis 实例上进行解锁,即使是上一步操作请求失败的节点,防止因为服务端响应消息丢失,但是实际数据添加成功导致的不一致。

 

3.基于zookeeper

ZooKeeper 有四种节点类型,包括持久节点、持久顺序节点、临时节点和临时顺序节点,利用 ZooKeeper 支持临时顺序节点的特性,可以实现分布式锁。

1.持久节点 (PERSISTENT)

默认的节点类型。创建节点的客户端与zookeeper断开连接后,该节点依旧存在

2.持久节点顺序节点(PERSISTENT_SEQUENTIAL)

所谓顺序节点,就是在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号

3.临时节点(EPHEMERAL)

和持久节点相反,当创建节点的客户端与zookeeper断开连接后,临时节点会被删除

4.临时顺序节点(EPHEMERAL_SEQUENTIAL)

顾名思义,临时顺序节点结合和临时节点和顺序节点的特点:在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号;当创建节点的客户端与zookeeper断开连接后,临时节点会被删除。

 

当客户端对某个方法加锁时,在 ZooKeeper 中该方法对应的指定节点目录下,生成一个唯一的临时有序节点。

 

 

 

判断是否获取锁,只需要判断持有的节点是否是有序节点中序号最小的一个,当释放锁的时候,将这个临时节点删除即可,这种方式可以避免服务宕机导致的锁无法释放而产生的死锁问题。

 

下面描述使用 ZooKeeper 实现分布式锁的算法流程,根节点为 /lock:

       客户端连接 ZooKeeper,并在 /lock 下创建临时有序子节点,第一个客户端对应的子节点为 /lock/lock01/00000001,第二个为 /lock/lock01/00000002;

      其他客户端获取 /lock01 下的子节点列表,判断自己创建的子节点是否为当前列表中序号最小的子节点;

      如果是则认为获得锁,执行业务代码,否则通过 watch 事件监听 /lock01 的子节点变更消息,获得变更通知后重复此步骤直至获得锁;

      完成业务流程后,删除对应的子节点,释放分布式锁。

      在实际开发中,可以应用 Apache Curator 来快速实现分布式锁,Curator 是 Netflix 公司开源的一个 ZooKeeper 客户端,对 ZooKeeper 原生 API 做了抽象和封装,若感兴趣可自行查询资料了解。

 

通过ZooKeeper实现起来比较方便,但是性能上可能并没有缓存服务那么高。因为每次在创建锁和释放锁的过程中,都要动态创建、销毁瞬时节点来实现锁功能。

 

 

文章主要整理自以下课程,如果想系统学习分布式技术原理与实战,可点击:

https://skaygo.blog.youkuaiyun.com/article/details/113850871

 

 

 

 

分布式锁实现解析:几种简单方式的对比与选择 本文分析了几种常见的分布式锁实现方式,包括基于Redis、ZooKeeper和数据库的方案。通过对每种方式的原理、优缺点进行深入剖析,本文旨在帮助开发者根据不同的应用场景选择合适的分布式锁实现。同时,文章还讨论了分布式锁的使用建议和最佳实践,为解决分布式系统中的并发控制问题提供了有效的参考。 阅读详情

相关推荐

基于稀疏表示字典学习的图像超分辨率-杨建超论文解析

文章:《Image Super-Resolution via Sparse Representation》 作者:杨建超 信号稀疏的定义: 令字典D的原子个数M,信号维度为N,则有以下三种关系: M = N时,D为完备的; M > N时,D为冗余的; M>>N时, D为过完备的。 图解如下: 借鉴了压缩感知的思想,通过对大量低分辨率图像和高分辨...

ycc18829026593的博客 7638

什么是分布式锁?分布式锁实现方式?

什么是分布式锁?几种分布式锁分别是怎么实现的?

u014644574的博客 1069

LabVIEW电压信号采集系统:从零搭建到科研实战

本文详细介绍了如何从零开始搭建一个基于LabVIEW的电压信号采集系统。内容涵盖硬件选型(如NI USB-6002数据采集卡)、软件环境配置、核心程序开发(包括多通道同步采集、数据自动保存)以及高级功能优化。系统支持自定义采样率与时长,并提供了完整的LabVIEW程序框图和配套的Python数据分析脚本,旨在帮助科研人员和工程师快速构建稳定、高效的专属数据采集方案,提升实验自动化水平。

gold8的专栏 462

什么是分布式锁?几种分布式锁分别是怎么实现的?

一、什么是分布式锁: 1、什么是分布式锁: 分布式锁,即分布式系统中的锁。在单体应用中我们通过锁解决的是控制共享资源访问的问题,而分布式锁,就是解决了分布式系统中控制共享资源访问的问题。与单体应用不同的是,分布式系统中竞争共享资源的最小粒度从线程升级成了进程。 2、分布式锁应该具备哪些条件: 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行 高可用的获取锁与释放锁 高性能的获取锁与释放锁 具备可重入特性(可理解为重新进入,由多于一个任务并发使用,而

weixin_74412978的博客 6295

OMNET++ INET框架学习教程(一)

在自组网学习的道路上摸石头过河,帮你快速入门OIMNET++平台下的INET框架。

NLDwangzhe的博客 6565

优快云独家 | 全网首发 | 《目标检测蓝皮书》目录

10篇文章从目标检测小白变大神

Coding... 3万+

深入理解Java中的分布式锁实现:从理论到实践

分布式锁在分布式系统中起着至关重要的作用,确保了在多节点环境下对共享资源的安全访问。本文详细介绍了Java中常用的三种分布式锁实现策略,即基于Redis、Zookeeper和数据库的分布式锁,并提供了相应的代码示例和优缺点对比表格。希望本文能够帮助你深入理解分布式锁的实现原理,并在实际项目中做出合适的选择。

weixin_53840353的博客 1356

Vue2 - 最新详细实现接入天地图详细配置流程及示例代码教程,提供获取用户当前定位的城市名称及省市区数据、精准经纬度信息、IP属地定位、地图搜索标点等示例,解决天地图跨域报错/页面白屏/定位不准问题

vue2,nuxt2,天地图,使用教程,vue接入国家天地图,定位api,ip属地定位,获取用户当前位置数据,省市区,地图不显示,白屏,报错,vue2如何使用天地图,地图选点,cors跨域,白名单设置了还是不行,vue项目调用天地图api实现定位,Vue2中使用天地图,详细教程,天地图申请密钥key教程,经纬度,经纬度不准确,一直定位北京,定位在北京不准怎么办,nuxt项目天地图,网站,网页,h5页面,地图显示不全,获取当前定位,如何使用天地图,拿到客户ip地址定位城市名称,距离计算,实时搜索地址逆解析,天

🏆 前端领域优质创作者 5329

说一下对分布式锁的理解,以及分布式锁的实现?

分布式锁是分布式系统中协调资源访问的关键工具,常见的实现方式包括基于数据库、Redis和ZooKeeper。选择实现方式时需根据具体需求和系统特点进行权衡。

w2369110547的博客 712

PCL RANSAC采样一致性算法

一直想了解一下RANSAC算法的一些原理,所以就趁着自己闲了下来整理了一下,做了这篇笔记。 文章目录一、简介二、PCL中的RANSAC 一、简介 RANSAC是一种随机参数估计算法。RANSAC从样本中随机抽选出一个样本子集,使用最小方差估计算法对这个子集计算模型参数,然后计算所有样本与该模型的偏差,再使用一个预先设定好的阈值与偏差比较,当偏差小于阈值时,该样本点属于模型内样本点(内点),否则就是外样本点(外点)。记录当前的内点的个数,然后重复上述的过程,直到模型中的内点达到最多,那么此时的模型参数即为最

dayuhaitang1的博客 2117

2025.06.06【Ribo-seq】|RiboCode:基于Ribo-seq数据的全基因组翻译ORF检测工具详解与实战流程

大家好!今天我们要学习的是RiboCode——一个专为Ribo-seq(核糖体足迹测序)数据设计的高质量翻译ORF(开放阅读框)检测工具。RiboCode能够帮助我们在全基因组范围内精准识别翻译事件,发掘经典CDS之外的uORF、dORF、重叠ORF等新型翻译本,极大拓展了我们对转录本翻译潜能的认知。RiboCode 是由清华大学杨学睿课题组开发的开源软件,支持Linux/Mac平台,采用Python实现。自动化流程:一条命令即可完成注释准备、P-site定位、ORF预测。高灵敏度与特异性。

1861

实现分布式锁的常用三种方式

我们的系统都是分布式部署的,日常开发中,秒杀下单、抢购商品等等业务场景,为了防⽌库存超卖,都需要用到分布式锁。分布式锁其实就是,控制分布式系统不同进程共同访问共享资源的一种锁的实现。如果不同的系统或同一个系统的不同主机之间共享了某个临界资源,往往需要互斥来防止彼此干扰,以保证一致性。业界流行的分布式锁实现,一般有这3种方式:基于数据库实现的分布式锁基于Redis实现的分布式锁基于Zookeeper实现的分布式锁分布式锁:基于数据库实现主要有两种方式:1、悲观锁2、乐观锁A. 悲观锁(排他锁)

2301_76166241的博客 3404

AMDGPU驱动中Doorbell与Event机制简要对比

摘要:AMDGpu驱动中,Doorbell和Event是两种异步通知机制。Doorbell是CPU→GPU的单向硬件通知,通过写MMIO寄存器触发GPU拉取任务,延迟低且无需内核介入,适用于队列任务提交。Event是GPU→CPU的双向同步通知,基于中断和内核事件对象,支持阻塞等待,用于任务完成或异常上报。核心区别在于方向、用途和实现方式:Doorbell侧重任务触发,Event侧重状态反馈。两者配合实现高效的任务下发与完成通知流程。

图形/计算GPU的驱动与虚拟化技术分享园地 1863

分布式锁简单入门以及三种实现方式介绍

很多小伙伴在学习Java的时候,总是感觉Java多线程在实际的业务中很少使用,以至于不会花太多的时间去学习,技术债不断累积!等到了一定程度的时候对于与Java多线程相关的东西就很难理解,今天需要探讨的东西也是一样的和Java多线程相关的!做好准备,马上开车! 学过Java多线程的应该都知道什么是锁,没学过的也不用担心,Java中的锁可以简单的理解为多线程情况下访问临界资源的一种线程同步机制。

徐刘根的博客 13万+

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

什么是分布式锁,分布式锁的几种实现方式

不具备可重入的特性,因为同一个线程在释放锁之前,行数据一直存在,无法再次成功插入数据,所以,需要在表中新增一列,用于记录当前获取到锁的机器和线程信息,在再次获取锁的时候,先查询表中机器和线程信息是否和当前机器和线程相同,若相同则直接获取锁;没有锁失效机制,因为有可能出现成功插入数据后,服务器宕机了,对应的数据没有被删除,当服务恢复后一直获取不到锁,所以,需要在表中新增一列,用于记录失效时间,并且需要有定时任务清除这些失效的数据;在这个例子中,锁用于控制访问数据库的流量,最终起到了保护系统的作用。

w_l666的博客 2127

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

分布式锁的实现方式有哪些

分布式有多少种实现方式?最后一种颠覆你的认知!

一个程序员的自我救赎。 1117

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

分布式锁的几种实现方式

分布式锁的几种实现方式 要如何实现对共享资源进行互斥操作呢? 锁就是其中一个非常通用的解决方案。在单节点多线程环境,你使用本地的互斥锁就可以 完成资源的互斥操作。然而单节点存在单点故障,为了保证服务高可用,你需要多节点部 署。在多节点部署的分布式架构中,你就需要使用分布式锁来解决资源互斥操作了。 分布式锁 分布式锁的三个 主要核心要素: 安全性、互斥性。在同一时间内,不允许多个 client 同时获得锁。 活性。无论 client 出现 crash 还是遭遇网络分区,你都需要确保任意故障场景下,都不 会出

你知道的越多,你不知道的越多 4331

一文理解分布式锁的实现方式

分布式锁的应用场景分布式锁的应用场景主要包括两类:处理效率提升:减少重复任务的执行,避免资源处理效率的浪费(例如幂等场景)。数据准确性保障:在数据资源的并发访问时,避免数据不一致情况,甚至...

全菜工程师小辉的博客 632

三种分布式锁实现方式

为什么要使用分布式锁 在之前的单体架构中 , 面对线程安全的问题可能使用 Java 提供的 ReentrantLcok 或 Synchronized 即可。但是随着业务不断发展,这时单机满足不了,于是采用分布式部署的方式。虽然一定程度解决了性能的瓶颈 , 但是也带来了许多分布式相关的问题。就分布式锁而言,看如下图: 单体应用部署结构: 分布式部署架构: 如上如所示,可以看出为什么需要分布式锁: 在电商业务采用分...

有个疙叫瘩儿的博客 3597

Java面试必备:分布式锁的实现方式详解

在分布式系统中,多个进程或服务需要协调对共享资源的访问时,分布式锁就成为了一个关键组件。本文将详细介绍分布式锁的常见实现方式,并通过流程图帮助理解各种实现机制。

qq_58299462的博客 2075

分布式锁的实现方式

通常我们说的锁,指的是单机单进程中多线程环境下,当多个线程同时访问共享资源时,会引发并发访问的问题,可能导致数据不一致或竞态条件。通过使用锁,可以确保一次只有一个线程能够访问共享资源,从而避免这些问题。通常使用的锁有:1)互斥锁2)自旋锁3)信号量4)读写锁5)原子变量以及内存屏障6)条件变量那么,如果是多个进程相互竞争一个资源,如何保证资源只会被一个操作者持有呢?

Ricardo2的博客 2807

分布式锁的三种实现方式

在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务、分布式锁等。有的时候,我们需要保证一个方法在同 一时间内只能被同一个线程执行。在单机环境中,Java中其实提供了很多并发处理相关的API,但是这些API在分布式场景中就无能为力了。也就是说单 纯的Java Api并不能提供分布式锁的能力。所以针对分布式锁的实现目前有多种方案: 分布式锁一般有三种实现方式:1...

qingshanpeiyu的博客 2589

分布式锁 4种主流实现方式

Redis+Redisson(生产首选,极致性能)、ZooKeeper(强一致性兜底)、数据库(应急入门)、RedLock(终极强一致)。

xiaolyuh的专栏 2314
上一篇: 分布式事务常用的解决方案
下一篇: Golang实现LRU Cache
思维的深度
博客等级 码龄11年 2万+粉丝 391原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值