技术广度必备——高并发设计之分布式锁的实现方式

在这里插入图片描述

文章目录

  • 问题背景
  • 前言
  • 实现
    • 基于MySQL实现
      • 唯一索引
      • 乐观锁
      • 悲观锁
    • 基于Redis
    • 基于Zookeeper
      • 原理
      • 使用Curator框架实现ZK分布式锁
      • 缺点

问题背景

研究有哪几种方案可以实现分布式锁,技术选型的场景下能用到。

前言

  1. 本文参考过的文章有分布式锁的几种实现方式
  2. 方式大致分为3种:基于磁盘存储的关系型数据库MySQL;基于内存的数据库Redis;基于Zookeeper

实现

基于MySQL实现

基于MySQL也有3种方式:基于唯一索引;基于MySQL行锁的乐观锁;基于悲观锁

唯一索引

利用唯一索引,在竞争锁时用insert操作,insert成功表示获取锁成功。下面专门创建一张表实现分布式锁:

CREATE TABLE `database_lock` (`id` BIGINT NOT NULL AUTO_INCREMENT,`resource` int NOT NULL COMMENT '锁定的资源',`description` varchar(1024) NOT NULL DEFAULT "" COMMENT '描述',PRIMARY KEY (`id`),UNIQUE KEY `uiq_idx_resource` (`resource`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据库分布式锁表';

通过insert操作竞争锁,通过delete操作释放锁。

优点:实现简单,复杂度低
缺点

  1. 锁没有过期时间。可以利用RocketMQ的延时消息或者延时线程池、利用定时任务使锁过期。
  2. 强依赖于数据库。建议设置备库或者集群,避免的单点数据库挂了,提高可靠性。
  3. 非阻塞。竞争锁失败则会继续往下执行业务,不会继续重试获取锁,也不会阻塞等待。可以使用 for、while实现阻塞等待或循坏尝试竞争锁。
  4. 非可重入。数据库表没有记录获取到锁的唯一信息(比如线程信息、进程信息、主机信息),增加字段记录这些信息实现可重入。竞争锁时根据自身的信息(线程信息、进程信息、主机信息)查询表,表中有记录则获取锁成功,实现了可重入。
  5. 如果并发高,则会有大量请求失败或者大量写压力给到数据库。

乐观锁

利用mysql自带的行锁机制,前提是本身就要在数据库里面有数据

CREATE TABLE `optimistic_lock` (`id` BIGINT NOT NULL AUTO_INCREMENT,`resource` int NOT NULL COMMENT '锁定的资源',`version` int NOT NULL COMMENT '版本信息',`created_at` datetime COMMENT '创建时间',`updated_at` datetime COMMENT '更新时间',`deleted_at` datetime COMMENT '删除时间', PRIMARY KEY (`id`),UNIQUE KEY `uiq_idx_resource` (`resource`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据库分布式锁表';

实现的SQL如下:

update optimistic_lock set resource =  xx, version = newVersion where id = xx and version = oldVersion;

解释:需要通过主键id去加行锁,否则会走范围锁或者表锁。更新时不仅要更新资源值,也要更新版本信息。查询需要带上版本号信息。

优缺点与唯一索引是宪法方式一样。大量并发下会有大量请求失败或者写压力很高,不适合高并发。

悲观锁

利用MySQL的X排他锁

在查询语句后面增加FOR UPDATE,数据库会在查询过程中给数据库表增加悲观锁,也称排他锁。当某条记录被加上悲观锁之后,其它线程也就无法再改行上增加悲观锁。

在使用悲观锁时,我们必须关闭MySQL数据库的自动提交属性(参考下面的示例),因为MySQL默认使用autocommit模式

mysql> SET AUTOCOMMIT = 0; 

这样在使用FOR UPDATE获得锁之后可以执行相应的业务逻辑,执行完之后再使用COMMIT来释放锁。

优点
在悲观锁中,每一次行数据的访问都是独占的,只有当正在访问该行数据的请求事务提交以后,其他请求才能依次访问该数据,否则将阻塞等待锁的获取。悲观锁可以严格保证数据访问的安全。

缺点

  1. 每次请求都会额外产生加锁的开销且未获取到锁的请求将会阻塞等待锁的获取,在高并发环境下,容易造成大量请求阻塞,影响系统可用性。另外,悲观锁使用不当还可能产生死锁的情况。

  2. 使用排他锁来进行分布式锁的lock,那么一个排他锁长时间不提交,就会占用数据库连接。一旦类似的连接变得多了,就可能把数据库连接池撑爆

基于Redis

详情见笔者写的大厂的Redis分布式锁是如何设计的

基于Zookeeper

原理

利用ZK的临时顺序节点实现分布式锁。

  1. ZooKeeper的每一个节点都是一个天然的顺序发号器在每一个节点下面创建临时顺序节点(EPHEMERAL_SEQUENTIAL)类型,新的子节点后面会加上一个顺序编号。这个顺序编号是在上一个生成的顺序编号加1。
  2. ZooKeeper节点的递增有序性可以确保锁的公平。一个ZooKeeper分布式锁,首先需要创建一个父节点,尽量是持久节点(PERSISTENT类型),然后每个要获得锁的线程都在这个节点下创建个临时顺序节点。由于Zk节点是按照创建的顺序依次递增的,为了确保公平,可以简单地规定,编号最小的那个节点表示获得了锁。因此,每个线程在尝试占用锁之前,首先判断自己的排号是不是当前最小的,如果是,则获取锁。
  3. ZooKeeper的节点监听机制可以保障占有锁的传递有序而且高效ZooKeeper内部优越的机制,能保证由于网络异常或者其他原因造成集群中占用锁的客户端失联时,锁能够被有效释放。一旦占用锁的ZNode客户端与ZooKeeper集群服务器失去联系,这个临时ZNode也将自动删除。排在它后面的那个节点也能收到删除事件,从而获得锁。所以,在创建取号节点的时候,尽量创建临时ZNode节点,
  4. ZooKeeper的节点监听机制能避免羊群效应ZooKeeper这种首尾相接,后面监听前面的方式,可以避免羊群效应。所谓羊群效应就是一个节点挂掉了,所有节点都去监听,然后作出反应,这样会给服务器带来巨大压力,所以有了临时顺序节点,当一个节点挂掉,只有它后面的那一个节点才作出反应。

使用Curator框架实现ZK分布式锁

详情见笔者写的SpringBoot基于Zookeeper实现分布式锁

Curator提供的InterProcessMutex是分布式锁的实现。acquire方法用户获取锁,release方法用于释放锁。

缺点

  1. 性能上: 性能上可能并没有缓存服务那么高。因为每次在创建锁和释放锁的过程中,都要动态创建、销毁瞬时节点来实现锁功能。ZK中创建和删除节点只能通过Leader服务器来执行,然后将数据同步到所有的Follower机器上。
  2. 并发问题: 使用Zookeeper也有可能带来并发问题,只是并不常见而已。考虑这样的情况,由于网络抖动,客户端可ZK集群的session连接断了,那么zk以为客户端挂了,就会删除临时节点,这时候其他客户端就可以获取到分布式锁了。就可能产生并发问题。这个问题不常见是因为zk有重试机制,一旦zk集群检测不到客户端的心跳,就会重试,Curator客户端支持多种重试策略。多次重试之后还不行的话才会删除临时节点。(所以,选择一个合适的重试策略也比较重要,要在锁的粒度和并发之间找一个平衡。)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/89800.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IDEA 设置字体大小无效

设置字体大小,一般都是从file>settings>editor>font>Size里设置,一般都有效。 但是,如果是更换了主体,则需要从主体颜色菜单那里这是,你看这个页面,上面黄色三角也提示你了,要去颜色…

风丘科技将亮相 EVM ASIA 2023

风丘科技将首次亮相 EVM ASIA 2023 WINDHILL will debut EVM ASIA 2023 ——可持续移动的未来 —The Future of SUSTAINABLE Mobility EVM ASIA 2023是亚太地区电气化的国际性展会,专注于新能源汽车、充电技术及汽车零件制造等。展会致力于促进包括充电站、交通…

【dnf5文档】新一代RedHat自动化包管理器

前言 HI,CSDN的码友们,距离上一次我发文章已经过去了半年的时间,现在我又来介绍自己新发现和探究的开源技术了。计算机的发展总是飞速的,当我在写这篇文章的时候,Fedora rawhide已经进入了40版本、默认采用的自动化包管理器为dnf…

论文阅读——Adversarial Eigen Attack on Black-Box Models

Adversarial Eigen Attack on Black-Box Models 作者:Linjun Zhou, Linjun Zhou 攻击类别:黑盒(基于梯度信息),白盒模型的预训练模型可获得,但训练数据和微调预训练模型的数据不可得&#xff…

SpringBoot Thymeleaf模板引擎

Thymeleaf 模板引擎 前端交给我们的页面,是html页面。如果是我们以前开发,我们需要把他们转成jsp页面,jsp好处就是当我们查出一些数据转发到JSP页面以后,我们可以用jsp轻松实现数据的显示,及交互等。 jsp支持非常强大…

【Linux】高级IO

目录 IO的基本概念 钓鱼五人组 五种IO模型 高级IO重要概念 同步通信 VS 异步通信 阻塞 VS 非阻塞 其他高级IO 阻塞IO 非阻塞IO IO的基本概念 什么是IO? I/O(input/output)也就是输入和输出,在著名的冯诺依曼体系结构当中…

k8s常用资源管理 控制

目录 Pod(容器组):Pod是Kubernetes中最小的部署单元,可以包含一个或多个容器。Pod提供了一种逻辑上的封装,使得容器可以一起共享网络和存储资源 1、创建一个pod 2、pod管理 pod操作 目录 创建Pod会很慢 Pod&…

MySQL表的增删查改

目录 一,新增 二,查询 2.1 全列查询 2.2 指定列查询 2.3 查询字段为表达式 2.4 别名 - as 2.5 去重 - distinct 2.6 排序 - order by 2.7 条件查询 - where 2.8 分页查询 - limit 三,修改 - update 四,删除 - delete 一…

考公-判断推理-定义判断

第九节课 例题 例题 例题 例题 例题 例题 脚一滑,就是工伤,这难道不是操作不当吗 例题 不要较真,公务员,把没有全局观念的人排除在公务员队伍之外 例题 例题 下次看到不字,先给我画上 例题 例题 例题 例题…

管理类联考——逻辑——论证逻辑——汇总篇——因果推理

因果推理的逻辑方法(穆勒五法) 确定现象之间因果关系的方法有五种: 求同法、求异法、求同求异并用法、共变法、剩余法。这五种方法统称为穆勒五法。用穆勒五法确定的因果关系具有或然性。 PS:求同球童;求异球衣,求同…

图解结构体大小和位域例子

struct A {short a; char b; int c : 1; char d : 4; short e : 7; }; 备注:蓝色:表示占一个符号位空间红色:表示补齐其他颜色:实际最大值所占空间 (1)图解例1 st…

opencv实战项目 手势识别-手势音量控制(opencv)

本项目是使用了谷歌开源的框架mediapipe,里面有非常多的模型提供给我们使用,例如面部检测,身体检测,手部检测等。 手势识别系列文章 1.opencv实现手部追踪(定位手部关键点) 2.opencv实战项目 实现手势跟踪…

答疑:Arduino IDE配置其他开发板下载速度慢

基于案例:Linux环境Arduino IDE中配置ATOM S3 通常,网络问题较多,可以使用一些技巧。 https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json 没有配置,不支持M5Stack(ESP32&…

【MongoDB基础】

目录 一、概述 1.概念 2.相关 2.1 实例 2.2 库 2.3 集合 2.4 文档 2.5 主键 3.特性 4,应用场景 二、安装 1.RPM安装 2.启动数据库 三、目录结构 1.rpm -ql mongodb-org-server 2.rpm -ql mongodb-org-shell 3.rpm -ql mongodb-org-tools 四、默…

【MySQL--->数据库基础】

文章目录 [TOC](文章目录) 一、基本概念二、实际应用中的数据库三、mysql的架构四、mysql语句分类五、存储引擎查看 一、基本概念 mysql本质是一个CS模式的网络服务,mysql是客户端,mysqld是服务端,提供高效的数据存取方案.数据库系统简单来说是一个数据集合加上管理这个数据集…

数据库数据恢复-Oracle数据库数据恢复案例

数据库数据恢复环境: Oracle数据库ASM磁盘组有4块成员盘。 数据库故障&分析: Oracle数据库ASM磁盘组掉线 ,ASM实例无法挂载,用户联系我们要求恢复oracle数据库。 数据库数据恢复工程师拿到磁盘后,先将所有磁盘以只…

Kafka的下载安装以及使用

一、Kafka下载 下载地址:https://kafka.apache.org/downloads 二、Kafka安装 因为选择下载的是 .zip 文件,直接跳过安装,一步到位。 选择在任一磁盘创建空文件夹(不要使用中文路径),解压之后把文件夹内容…

Android:换肤框架Android-Skin-Support

gihub地址:https://github.com/ximsfei/Android-skin-support 样例: 默认: 更换后: 一、引入依赖: // -- 换肤依赖implementation skin.support:skin-support:4.0.5// skin-supportimplementation skin.support:ski…

9-AJAX-1入门

AJAX 目录 AJAX 概念和 axios 使用认识 URLURL 查询参数常用请求方法和数据提交HTTP协议-报文接口文档案例 - 用户登录form-serialize 插件 01.AJAX 概念和 axios 使用 目标 了解 AJAX 概念并掌握 axios 库基本使用 讲解 什么是 AJAX ? mdn 使用浏览器的 XMLHttpRequest…

kubernetes中PV和PVC

目录 一、PV、PVC简介 二、PV、PVC关系 三、创建静态PV 1.配置nfs存储 2.定义PV 3.定义PVC 4.测试访问 四、 搭建 StorageClass nfs-client-provisioner ,实现 NFS 的动态 PV 创建 1. 配置nfs服务 2.创建 Service Account 3.使用 Deployment 来创建 NFS P…