分布式锁的原理解析与实现工具介绍

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 Tair(兼容Redis),内存型 2GB
简介: 分布式锁的原理解析与实现工具介绍

锁与IPC

常见的锁:互斥锁、自旋锁、原子变量、读写锁、条件变量、信号量。

IPC(进程间通信的方式):pipe、FIFO、信号量、消息队列、共性内存、socket、信号。

(拓展)虚假唤醒解决:把pthread_cond_wait放在while循环体里面,循环里判断condition是否满足。由此还能解决信号劫持的问题,比如线程池里只有一个任务,但是signal唤醒了多个消费者线程,于是需要加入判断,只能有一个线程得到满足。

分布式锁

分布式锁:在分布式场景中使用的锁。操作系统并没有提供分布式锁,只能由用户自行实现。这个锁是抽象的锁,并不是真正的锁。

分布式场景:执行程序、存储等分布在多个节点(节点通常是独立的计算机或设备等)的场景。

分布式场景的特点:执行体分布在不同的节点上,一个节点至少是一个进程。

分布式场景与锁简化模型:

如图,如果s1\s2\s3\s4都想去操作DB(数据库),但是DB同一时间最多只允许一个节点操作,那么需要设置一个锁(lock)放在s1\s2\s3\s4均能取到的地方(比如数据库,有可能和要操作的数据库放在了一起,不过在不同的表里),谁能拿到锁谁就能去操作数据。

分布式锁的构成:资源+行为。

资源:是获取到锁的节点的id(比如s1的id)。

行为:加锁和解锁,分布式场景中加锁和解锁的方式都通过网络通信的方式实现。

加锁:原来没有标记,获取到锁之后打上标记。

解锁:持锁方取出标记。

特性:

锁超时:对持锁方能持有锁的最长时间有限制,如果持锁方崩坏,不至于让其他节点也获取不到资源。

可用性和容错性其实差不多,只不过容错性更侧重数据一致性,可用性更侧重共享节点崩坏的处理。

分布式锁的类型:

重入锁:允许线程多次持有锁。

公平锁:对应互斥锁。拿不到互斥锁的线程进入阻塞态,id进入阻塞队列。

非公平锁:对应自旋锁。拿不到自旋锁的线程进入阻塞态,但是忙等待。

分布式锁的实现工具

需要基于中间件来实现,资源存储在中间件当中,加锁解锁行为基于中间件的特性来实现。

以下分别以mysql和redis为例来实现分布式锁。

用mysql实现分布式锁

首先需要建立在mysql数据库里建立用于存储锁的table,加锁的时候还要记录加锁的时间,因此设置了一个字段记录锁建立的时间。锁类型唯一,说明只能被获取一次,注意:这里的锁类型不是互斥锁、自旋锁等,而是活动1的锁、活动2的锁等。

用户节点加锁。用户节点会将以下sql语句发送到mysql数据库进行加锁操作,如果有多个用户节点,那么先发送到的节点先获取到锁,后发送到的节点会获得操作失败的信息。因为lock_type唯一,因此只有一个节点能获取到锁,获取到锁的时候数据还有记录获取到了锁的owner_id。。

用户节点解锁。解锁的时候owner_id要和之前加锁的时候的记录匹配才能解锁。

其他想获取锁但是没能获取到锁的用户节点,只能每隔一段尝试向mysql去获取一次(因为mysql不会主动通知解锁操作),看看有没有解锁。因此mysql只能实现非公平锁。

Mysql还存在锁超时问题解决,即多起一个进程去检测锁从更新时间已经过了多久了,超时了就解锁。

因此我们发现mysql实现分布式锁有这些缺点:

  1. mysql分布式锁没有可用性。但mysql节点发生了故障,整个分布式系统就会失效。
  2. 消耗资源较多。要实现锁超时操作需要另开进程。
  3. 效率不高。其他用户节点需要不断轮询看看mysql是否解锁了,mysql‘节点不会主动发起通知。
  4. 功能有限。只能是新非公平锁。

用redis实现分布式锁

Redis的特性:

  1. 内存数据库。它将数据存储在内存中而不是磁盘中。
  2. 数据结构数据库。 Redis是一种键值对存储,键一般使用字符串(不绝对)类型,值可以是字符串、哈希表、列表、集合、有序集合等各种类型。

因为redis是一句数据库,启动了之后,会进入redis服务器的运行态,在这上面可以数据redis的操作命令,redis有自己的原语操作命令。

Redis收到以下命令,说明在完成相应的锁操作:

Setnx lock1 user1:用户1尝试抢锁并进行加锁(setnx:set no lock)。

Get lock1:某个用户在尝试看看是谁持有lock1。

Del lock1:如果用户发现锁的持有者是自己,那么可以进行解锁。

注意:get lock1和del lock1需要实现原子性,可以用redis的lua脚本实现。

Set lock user1 nx ex 20:Setnx lock1 user1的拓展版,多了20s之后会自动删除记录的功能,实现锁超时功能。

Ttl lock1:看看lock1还有多久被删除。

Redis分布式锁的lua脚本

用户节点向redis发送命令,redis去执行lua脚本。脚本的具体实现不用被用户知道,但此处进行一下redis的lua脚本的大致解析。

加锁:

先判断锁是否存在。如果不存在则设置锁与超时时间,如果存在则进入监听状态,监听未来释放锁的广播。

解锁:

解锁成功的时候要进行广播,告知给正在监听的用户。

注意防范锁不存在、锁与用户不匹配等问题。如果出现了这些情况那么直接return。

Red-lock算法

目录
相关文章
|
4天前
|
存储 缓存 算法
HashMap深度解析:从原理到实战
HashMap,作为Java集合框架中的一个核心组件,以其高效的键值对存储和检索机制,在软件开发中扮演着举足轻重的角色。作为一名资深的AI工程师,深入理解HashMap的原理、历史、业务场景以及实战应用,对于提升数据处理和算法实现的效率至关重要。本文将通过手绘结构图、流程图,结合Java代码示例,全方位解析HashMap,帮助读者从理论到实践全面掌握这一关键技术。
32 13
|
22天前
|
运维 持续交付 云计算
深入解析云计算中的微服务架构:原理、优势与实践
深入解析云计算中的微服务架构:原理、优势与实践
56 1
|
1月前
|
存储 Dubbo Java
分布式 RPC 底层原理详解,看这篇就够了!
本文详解分布式RPC的底层原理与系统设计,大厂面试高频,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
分布式 RPC 底层原理详解,看这篇就够了!
|
18天前
|
机器学习/深度学习 存储 运维
分布式机器学习系统:设计原理、优化策略与实践经验
本文详细探讨了分布式机器学习系统的发展现状与挑战,重点分析了数据并行、模型并行等核心训练范式,以及参数服务器、优化器等关键组件的设计与实现。文章还深入讨论了混合精度训练、梯度累积、ZeRO优化器等高级特性,旨在提供一套全面的技术解决方案,以应对超大规模模型训练中的计算、存储及通信挑战。
48 4
|
1月前
|
运维 持续交付 虚拟化
深入解析Docker容器化技术的核心原理
深入解析Docker容器化技术的核心原理
45 1
|
23天前
|
供应链 算法 安全
深度解析区块链技术的分布式共识机制
深度解析区块链技术的分布式共识机制
46 0
|
23天前
|
存储 供应链 算法
深入解析区块链技术的核心原理与应用前景
深入解析区块链技术的核心原理与应用前景
47 0
|
26天前
|
JavaScript 前端开发 API
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
54 0
|
1月前
|
API 持续交付 网络架构
深入解析微服务架构:原理、优势与实践
深入解析微服务架构:原理、优势与实践
28 0
|
1月前
|
存储 供应链 物联网
深入解析区块链技术的核心原理与应用前景
深入解析区块链技术的核心原理与应用前景

推荐镜像

更多
下一篇
DataWorks