分布式架构 --- 分布式锁

article/2025/10/13 4:18:23

分布式锁

  • 1. 研究背景及其意义
  • 2. 分布式锁的介绍
    • 2.1 分布式锁
    • 2.2 为什么需要分布式锁
    • 2.3 分布式锁的基本要求
  • 3. 分布式锁的实现
    • 3.1 基于数据库的分布式锁
      • 3.1.1选用数据库实现分布式锁的原因
      • 3.1.2 基于数据库实现分布式锁的缺点
      • 3.1.3分布式锁的实现
    • 3.2 基于Redis的分布式锁
      • 3.2.1选用Redis实现分布式锁的原因
      • 3.2.2基于Redis实现分布式锁的缺点
      • 3.2.3 基于Redis的分布式锁的实现
    • 3.3 基于Zookeeper的分布式锁
      • 3.3.1选用Zookeeper实现分布式锁的原因
      • 3.3.2 Zookeeper实现分布式锁的缺点
      • 3.3.3基于Zookeeper的分布式锁的实现
  • 4. 三种分布式锁实现方式的比较
  • 5. 总结

摘要:分布式锁是用于控制分布式系统之间访问共享资源。在分布式系统中,为了保证数据的一致性,我们常常会用到分布式锁。当同一个系统的不同主机或者不同的系统之间之间共用一个或者一组资源时,当我们访问这些资源的时候,面对不同用户的操作,我们需要防止各个操作之间相互独立,相互不收影响,以此来保证数据的一致性,这时,我们就需要用到分布式锁。比如,我们出行需要抢购火车票时,火车票的总数是不变的,但是火车票备份发在多个平台售卖,火车票总数不能超过限定票数,更不允许同一个座位的火车票不能卖给多个人,这样的场景就需要分布式锁对共享资源进行保护。
首先,本文主要对分布式锁进行基本介绍;其次,对分别基于数据库、Redis、Zookeeper实现分布式锁的三种方式的优缺点以及实现方法进行简述;最后,对分布式锁进行总结,并从不同方面比较基于三种方式实现分布式锁的性能。
关键词:分布式;Zookeeper;数据库;Redis;锁

1. 研究背景及其意义

  • 随着我国网络时代的发展,电子商务也越来越发达,我们可以同一时间,在不同地点去访问同一个软件,去参与同一个活动。但,如果应用只部署在少数几台服务器中,那么,数以千万的访问并发量容易导致服务器压力过大,严重时会导致服务器瘫痪。在618,双十一,年货节等节假日优惠活动时,用户访问量以及购买量将远远大于平常,往往一台服务器是不能够去实现的,这时候,我们就需要多台服务器去同时处理这些任务。
  • 我们可以拿除夕夜晚上支付宝分发红包进行举例,假设有50台服务器去处理这些分红包的业务,红包总金额为1亿,2千万人去分,金额随机,那么在这个业务场景下,我们必须得保证这2千万人分得的总金额数为1亿,如果同一个时刻,多个用户进行操作,就会导致系统扣除金额混乱,从而导致金额总和远远大于1亿,这会给商家带来很严重的经济损失,通过分布式锁,我们就可以很好地处理这些问题;

2. 分布式锁的介绍

2.1 分布式锁

  • 分布式锁是指分布式环境下,系统集群部署,实现多进程分布式互斥的一种锁。
  • 为了保证多个进程能看到锁,锁被存在公共存储(比如 Redis、Memcache、数据库等三方存储中),以实现多个进程并发访问同一个临界资源,同一时刻只有一个进程可访问共享资源,确保数据的一致性。

2.2 为什么需要分布式锁

  • 在单机应用程序开发环境中,当线程需要并发同步时,对于多线程间涉及到的的代码同步问题,我们一般采用synchronized/Lock的方式来进行解决,同时,我们将基于锁来检查多个线程间对资源的安全访问。例如,在文件读写系统中,用户想要进行一个写操作,那么写进程就需要检查系统是否存在一个写线程锁。
  • 如果存在一个写线程锁,那么我们就需要等待直到锁释放后,才能去争夺资源,才有可能获取到属于该线程的锁并进行写操作,这样,通过锁就可以避免多个线程同时写操作造成的数据冲突。而对于读进程,往往是可以多个读进程一起执行的,但过大的访问量,也会给系统带来很大的压力。此时,单台服务器已经无法满足我们的需求。但当我们的应用处于分布式环境下工作时,基本锁已经不再适用,这时候,我们就需要一种更加高级的锁机制来处理这个进程级别的代码同步和并发问题。
  • 其实,操作系统中提供了许多内置的函数,以帮助程序员来实现并发控制。但是,对于运行分布在多台机器上的多线程的程序来说,我们无法再通过操作系统的内置函数来实现对资源的控制。如果借助关系数据库事务来实现锁,这种方法会有许多不足,例如性能差、稳定性不足。所以,我们必须引入分布式锁来约束并发操作。

2.3 分布式锁的基本要求

分布式锁,是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,分布式锁对系统资源和数据起到了一个很好的协调作用。为了保证分布式锁可用,我们在确保锁实现的同时,需要至少满足以下几个条件:
(1)互斥性:在任何时候,锁只能由一个客户端获取,而不能由两个或多个客户端同时获取。
(2)高可用的获取锁与释放锁;
(3)高性能的获取锁与释放锁;
(4)具备可重入特性;
(5)具备锁失效机制:由于某些原因(如宕机等),获取锁的客户端未能及时释放锁,导致其它客户端无法进行获取,从而导致死锁,导致进程无法进行下去。因此,分布式锁应具备锁失效机制。
(6)具备非阻塞锁特性:当客户端没有获取到锁时,应直接将信息返回,通知获取锁失败。

3. 分布式锁的实现

分布式锁主要用于解决分布式系统中数据不一致的问题,分布式锁一般有3种实现方式:
(1)基于数据库的分布式锁;
(2)基于 Redis的分布式锁;
(3)基于ZooKeeper的分布式锁。

3.1 基于数据库的分布式锁

3.1.1选用数据库实现分布式锁的原因

  • 优点:简单,易实现;

3.1.2 基于数据库实现分布式锁的缺点

  • 没有锁失效机制、可用性、性能较差;
  • ·当并发量较大时,对数据库压力较大;

3.1.3分布式锁的实现

  • (1)基于表记录

最简单的方法是直接创建一张锁表,通过操作该表中的数据来实现分布式锁,此时,我们对method_name做一些唯一性约束。以保证,数据库同时接收到多个请求,保证只有一个操作可以成功获取锁,假设某个线程操作成功,那么我们可以认为该线程获得了该方法的锁,也就说明可以开始执行方法体内容。当我们想要获取某个资源时,我们就要向表中添加一条数据,执行完成相应方法体后删除对应的行数据即表示释放锁。

  • (2) 悲观锁

基于select … where … for update 排他锁来实现的,我们可以认为,获得排它锁意味着获得了分布式锁,接着进一步,我们就可以执行方法的业务逻辑,并通过connection.commit()操作来提交事务,从而释放锁。但是,数据库单点问题和可重入问题,在悲观锁中还是无法得到直接解决。

  • (3) 乐观锁

乐观锁是基于CAS思想(Compare and swap(比较与交换),用来解决多线程并发情况下使用锁造成性能开销的一种机制)来实现的,但不具有互斥性,并不会进行加锁,而是假设可以没有冲突的去完成某项操作,操作过程中认为不存在并发冲突,我们是通过增加递增的version字段对乐观锁进行实现。
若数据库中的version字段值和更新时携带的version字段值不同,则表示更新失败(即返回0)。由于写一条sql都需要判断,增加了数据库操作的次数,在高并发的一下,对数据库连接的开销是巨大的。

3.2 基于Redis的分布式锁

3.2.1选用Redis实现分布式锁的原因

(1)Redis是建于内存高性能数据库;
(2)Redis命令对此支持较好,实现起来较为方便;

3.2.2基于Redis实现分布式锁的缺点

(1)Redis实现分布式锁,需要自己不断地去尝试获取锁,比较消耗性能(需要轮询,占用CPU资源);
(2)如果在集群中,出现master宕机的情况。此时,锁key还没有同步到slave节点上,这时候会出现机器B从新的master上获取到了一个重复的锁的现象;
(3)假设拥有Redis锁的客户端因为某些原因挂了,如果想要释放锁,那么只能等到设定的超时时间到了。

3.2.3 基于Redis的分布式锁的实现

图一 基于Redis实现的分布式锁

(1)一般来讲,我们会使用setnx加锁,并设置一个唯一的分布式锁key,并对key设置对应的客户端唯一的标识。为了避免死锁,我们可以通过expire命令为锁设置一个超时时间,超过时间则自动释放锁。我们可以设置一个随机生成的UUID(随机字符串)来表示锁的value值,来判断在某一时刻是否释放该锁;
(2)我们在获取锁的同时还应设置一个获取的超时时间,若是在时间内一直未获取到锁,则表示放弃获取该锁;
(3)当释放锁时,我们需要通过UUID来判断锁的确定性,若是该锁,则执行delete命令进行锁释放。

3.3 基于Zookeeper的分布式锁

3.3.1选用Zookeeper实现分布式锁的原因

(1)Zookeeper具备高可用、可重入、阻塞锁等特性,有较好的的性能和可靠性;
(2)Zookeeper可解决失效死锁的问题;
(3)当获取不到锁时,我们可以通过注册个监听器,来自动尝试获取锁,因此,性能开销较小。
(4)当获取锁的客户端由于某些原因挂了,因为在Zookeeper中,创建的是临时znode,只要客户端挂了,临时节点znode就会消失,此时锁就会自动被释放;

3.3.2 Zookeeper实现分布式锁的缺点

(1)需要频繁的创建和删除节点,获取锁和释放锁都需要在Leader上执行,然后同步到Follower中,因此,在性能上不如Redis实现的分布式锁。
(2)易出现“羊群效应”;

3.3.3基于Zookeeper的分布式锁的实现

基于Zookeeper的分布式锁的实现

基于Zookeeper的分布式锁的实现,主要有以下两种方法。

(1)可以借助开源库进行实现,例如,Apache的开源库Curator,是一个Zookeeper客户端。它提供的InterProcessMutex是可重入互斥锁,跨JVM工作,可以帮助我们来实现分布式锁。通过acquire方法来获取锁,release方法来释放锁。

(2)也可以通过自己编写,创建节点(临时节点)即加锁,删除节点即解锁,基于ZooKeeper实现分布式锁的步骤如下:
(1)创建一个目录mylock;
(2)某一时刻,线程thread_A想要申请获取锁,需要在mylock目录下创建临时顺序节点;
(3)获取mylock目录下所有的子节点后,然后寻找比自己小的兄弟节点,若找到并获取,若未找到,则说明不存在,表示当前线程顺序号最小,从而申请获得锁;
(4)线程thread_B想要获取锁,则它也要获取所有节点,判断自己不是最小节点,若不是,则需要设置监听比自己次小的节点;
(5)当线程thread_A的业务逻辑处理完之后,会删除自己的节点,线程thread_B监听到了事件变更,会重新判断自己是不是最小的节点,如果是,则申请获得锁。

4. 三种分布式锁实现方式的比较

实现方式实现思路优点缺点
基于数据库利用数据库自身提供的锁机制,要求数据库支持行级锁。实现简单,稳定可靠。性能差,无法适应高并发的场所;容易出现思索的情况。
基于Redis使用setnx和lua脚本机制实现,保证对存序列的原子性操作。性能好。实现相对较复杂,有出现思索的可能性。
基于Zookeeper基于zk的节点特性以及watch机制实现。性能较好,可靠性高,有较好的实现阻塞锁。实现相对复杂。

5. 总结

对于分别基于数据库、Redis、Zookeeper实现分布式锁的三种方式,任一方法都无法做到完美,都有利有弊。就像CAP理论一样,在性能、可靠性、复杂性等方面无法同时满足,所以,我们在使用分布式锁的时候应该根据业务场景来进行选择。

从各个角度对比可以得到以下结论:
(1)从理解的难易程度角度(从低到高):数据库 > Redis > Zookeeper
(2)从实现的复杂性角度(从低到高):Zookeeper >= Redis > 数据库
(3)从性能角度(从高到低):Redis > Zookeeper >= 数据库
(4)从可靠性角度(从高到低):Zookeeper > Redis > 数据库

参考文献:
[1]朱永超. 异构分布式系统的可靠性任务调度策略研究[D]. 南京理工大学.
[2]陈文武. 分布式锁技术研究[D]. 华南理工大学.
[3]周梅. 分布式锁的设计与实现[J]. 计算机工程, 2008, 34(16):3.
[4]徐彬. 基于分布式处理技术的物联网数据库创新研究与设计探析[J]. 数字通信世界, 2021(12):3.
[5]赖歆. 基于Redis的分布式锁的实现方案[J]. 信息通信, 2016(10):2.
[6]张俊. 基于Redis实现关系型数据库内存化研究[D]. 四川师范大学.
[7]韩雅丽. 分布式Redis高可用集群的设计与实现. 南京大学, 2019.
[8]刘芬, 王芳, 田昊. 基于Zookeeper的分布式锁服务及性能优化[C]// 2014:6.
[9]黄毅斐. 基于ZooKeeper的分布式同步框架设计与实现[D]. 浙江大学, 2012.
[10]赵玉京. 基于Zookeeper的分布式范围锁的设计与实现[D]. 华中科技大学, 2015.
[11]陈玉林, 王武. Zookeeper分布式锁的4种异常状态分析[J]. 2022(9).
[12]肖国云. 大数据时代电子商务安全问题探讨[J]. 商展经济, 2022(4):3.
[13]陈飞. 基于中间件的分布式服务器负载均衡方法[J]. 电子技术与软件工程, 2020(3):2.
[14]丁学智. 一种面向分布式服务器集群的动态负载均衡系统的实现[J]. 北京邮电大学, 2013.
[15]张君. 操作系统中进程死锁的探讨[J]. 电脑知识与技术:学术版, 2012, 8(1):3.
[16]陈更力,张青. Java并发线程中的死锁问题研究[J]. 长江大学学报自然科学版:理工卷(2期):72-75.
[17]朱洪伟. 基于单机的计算机网络实验平台的实现与应用[J]. 科技风, 2013(4):1.


http://chatgpt.dhexx.cn/article/ZnFbbl0X.shtml

相关文章

分布式锁的区别

分布式锁,是一种思想,它的实现方式有很多。比如,我们将沙滩当做分布式锁的组件,那么它看起来应该是这样的 加锁 在沙滩上踩一脚,留下自己的脚印,就对应了加锁操作。其他进程或者线程,看到沙滩上…

分布式锁的实现方式

背景 分布式场景中的数据一致性问题一直是一个比较重要的话题。分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance&#xff09…

分布式锁-Redisson

分布式锁 1、分布式锁1.1 本地锁的局限性1.1.1 测试代码1.1.2 使用ab工具测试(单节点)1.1.3 本地锁问题演示(集群情况) 1.2 分布式锁实现的解决方案1.3 使用Redis实现分布式锁(了解即可)1.3.1 编写代码1.3.2 压测 1.4 使用Redisson解决分布式锁1.4.1 实现代码1.4.1 压测1.4.2 可…

Redis 分布式锁

文章目录 一、分布式锁概念二、使用setnx实现锁三、编写代码测试分布式锁1. 使用Java代码测试分布式锁2. 优化之设置锁的过期时间 四、优化之给lock设置UUID防误删五、使用LUA脚本保证删除的原子性 一、分布式锁概念 随着业务发展的需要,原单机部署的系统被演化成分…

关于分布式锁

先别说了别的,先来一个总结。 synchronized 单机版可以,但是上了分布式就不行了。 nginx 分布式服务单机锁就不行 取消单机锁,上redis分布式锁setnx 注意的问题: 如果只加了锁,没有释放锁,出现异常的话…

Redisson分布式锁详解

概述 setnx分布式锁的问题 重入问题 重入问题是指获得锁的线程可以再次进入到相同的锁的代码块中,可重入锁的意义在于防止死锁,比如HashTable这样的代码中,它的方法都是使用synchronized修饰的,假如它在一个方法内,…

redission实现分布式锁

在开始提到Redis分布式锁之前,先说一下redis中的两个命令。 SETNX key valuesetnx 是SET if Not eXists(如果不存在,则 SET)的简写。 用法如图,如果不存在set成功返回int的1,这个key存在了返回0。 SETEX key seconds value上面…

Java分布式锁

文章目录 1.什么是锁?2.什么是分布式?分布式场景 3.什么是分布式锁?4.我们应该怎么设计分布式锁?5.基于数据库的分布锁5.1 基于表主键唯一做分布式锁5.2 基于表字段版本号做分布式锁 6.基于 Redis 做分布式锁6.1 基于 REDIS 的 SE…

Redis分布式锁

概述 日常开发中,秒杀下单、抢红包等等业务场景,都需要用到分布式锁。而Redis非常适合作为分布式锁使用。本文将分七个方案展开,跟大家探讨Redis分布式锁的正确使用方式。如果有不正确的地方,欢迎大家指出哈,一起学习一…

Zookeeper分布式锁

实现一把分布式锁通常有很多方法,比较常见的有 Redis 和 Zookeeper。 Redis分布式锁可参考之前的文章: Redisson 分布式锁原理分析:https://blog.csdn.net/qq_42402854/article/details/123342331 Zookeeper能实现分布式锁,是因…

分布式锁

分布式锁实践 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段。有很多三方库和文章描述如何用Redis实现一个分布式锁管理器,但是这些库实现的方式差别很大,而且很多简单的实现其实只需采用稍微增加一点复杂的设计就可…

分布式系列之分布式锁几种实现机制

在分布式系统中,分布式锁用来解决分布式系统中多线程、多进程在不同机器上共享资源访问的问题。本文简要介绍分布式锁的四种实现机制,包括数据库、Redis缓存、Zookeeper和Etcd,以加深了解。 1、分布式锁介绍 在单体应用中,通过锁…

三种分布式锁

----------本文为学习记录如有错误帮忙指正 一、什么是分布式锁? 在单机系统下,如果多个线程同时访问一个变量或者代码片段就会产生多线程问题。(被访问的变量或者代码片段被称之为临界区域)这时我们就需要让所有线程按顺序一个一…

Redis实现分布式锁

目录 一、前言 为什么需要分布式锁? 二、基于redis实现分布式锁 为什么redis可以实现分布式锁? 如何实现? 锁的获取 锁的释放 三、如何避免死锁?锁的过期时间如何设置? 避免死锁 锁过期处理 释放其他服务的锁…

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

一、什么是分布式锁: 1、什么是分布式锁: 分布式锁,即分布式系统中的锁。在单体应用中我们通过锁解决的是控制共享资源访问的问题,而分布式锁,就是解决了分布式系统中控制共享资源访问的问题。与单体应用不同的是&am…

软件需求最佳实践笔记(一)

1.软件需求最佳实践笔记 | 需求框架 前言:SERU是一套系统全面的需求方法论,可指导我们日常的软件需求工作。曾参加过徐峰老师软件需求最佳实践课程的培训,收益颇多,现通过笔记形式整理出来,以期与具有同样需求的读者共…

声音信号基音提取算法基频和谐波处理分析

1、内容简介 略 293-可以交流、咨询、答疑 2、内容说明 略 一、 实验原理: 傅里叶变换建立了信号频谱的概念。所谓傅里叶分析即分析信号的频谱(频率构成)、频带宽度等。要想合成出一段音乐,就要了解该段音乐的基波频率、谐波构成等。因此,必须采用傅里叶变换这…

软件工程—需求分析阶段

第一步、需求获取 为了保证能全面地获取信息,以更好地服务于产品设计和迭代,产品经理必须利用内部外部等多种渠道来获取用户需求。并且因渠道差异,产品经理所采取的方式与方法也相应会有所差异,所以产品经理还必须根据不同的渠道…

作业1.1利用Audacity软件分析音频

文章目录 前言实验内容实验步骤实验结果结果分析总结 前言 Audacity软件分析其余格式的音频时需要安装FFmpeg库,所以我们下载一个格式转换软件将音频转为MP3格式进行处理。语音信号具有短时平稳性,即在一个短时间范围内(10-30ms)…

C++ OBS源码分析与屏幕录制软件开发视频教程

本课程主要讲解OBS源码的编译,OBS功能实现,初始化,显示器录制,窗口的实现录制,以及录制模块源码详细分析,最后基于OBS源码开发了一个录制软件,界面如下: 主要有如下功能 &#xff0…