(面试经典问题之分布式锁)分布式锁的基本原理、作用以及实现

一、什么是分布式锁

分布式锁指的是在分布式场景中实现互斥类型的锁。

分布式是什么意思?分布式表示运行的节点可能在不同的机器或不同的网段中,节点间通信通过socket。互斥类型是什么意思?互斥类型表示同一时刻只允许一个执行体进入临界资源。

二、分布式锁的特性

分布式锁具有三大特性:

1、互斥性:同上所述,互斥性要求同一时刻只允许一个执行体进入临界资源。具体的操作包括加锁、解锁、给执行体打上唯一标记。

2、锁超时性:由于其分布式的特性(节点间需要通过网络进行通信),而一旦某获取了锁的节点出现网络故障或者进程宕机,从而无法释放锁,这将导致其他尝试获取该锁的节点或进程一直阻塞。因此,为避免该情况的发生,需要对其设置锁超时特性,即在某节点获取锁的时候设定一个时间,当超过该时间后该节点自动释放锁资源。

3、可用性:通俗来讲就是在合理时间内得到合理的回复。具体展开来又可细分为:

  • 高可用性:确保即使部分节点故障,锁的机制仍然能保持有效,避免系统宕机。
  • 网络分区容忍性:能够合理处理网络分区情况,确保系统的正常运行。
  • 死锁防止:通过超时机制等方式,避免死锁的发生。
  • 性能和响应时间:保持高效的锁操作,减少性能开销。

三、解决了什么问题 

在分布式场景下,只允许一个节点执行某类任务。

四、分布式锁的实现问题

常见的分布式锁的实现方式为:

  • 基于 Redis 实现分布式锁
  • 基于 ZooKeeper 实现分布式锁
  • 基于 Etcd 实现分布式锁
  • 基于 Mysql 实现分布式锁

看到这读者是否有产生跟我一样的疑问:分布式锁在层次结构上应属于“基础组件”层次,而redis,mysql这些属于“中间件”层次,正常来说,中间件是在基础组件的基础上实现的,那为什么这里反而是基于中间件去实现基础组件呢? 

原因在于,像redis这样的中间件,它们提供了构建分布式锁所需的原子操作,而这些原子操作是实现分布式锁的基础。换句话说,redis等这些中间件,它们的某些功能(SETNX EXPIRE)可以非常有效的用于实现分布式锁,我们基于redis实现分布式锁就是基于这些他们自带的功能。

这里以使用redis实现分布式锁举例:

import redis
import uuid
import time# 创建 Redis 连接
r = redis.StrictRedis(host='localhost', port=6379, db=0)lock_key = "my_lock"
lock_value = str(uuid.uuid4())  # 锁的唯一标识
lock_timeout = 10  # 锁的超时时间(秒)# 获取锁
def acquire_lock():# 使用 SETNX 设置锁并设置过期时间if r.setnx(lock_key, lock_value):r.expire(lock_key, lock_timeout)return Truereturn False# 释放锁
def release_lock():# 只有锁的持有者才能释放锁if r.get(lock_key) == lock_value:r.delete(lock_key)# 使用锁
if acquire_lock():try:print("Lock acquired, doing work...")time.sleep(5)  # 模拟任务执行finally:release_lock()print("Lock released")
else:print("Unable to acquire lock")
  • SETNX:用于设置一个值,仅当该键不存在时才设置。如果 Redis 返回 True,则表示锁成功获取;否则,表示锁已被其他客户端占用。
  • expire:为锁设置超时时间,避免死锁发生。如果客户端崩溃或网络中断,锁会在超时后自动释放。
  • DEL:释放锁时,首先需要检查当前锁值是否与客户端的值匹配,防止误删其他客户端的锁。

综上所述: 

  • Redis 本身并没有直接提供“分布式锁”功能,但它提供了支持实现分布式锁所需的基础操作(如 SETNXEXPIRE)。
  • 基于这些操作,我们可以构建一个分布式锁系统。因此,可以说 Redis 提供了实现分布式锁的基础构建块,但实现分布式锁的功能依赖于如何使用这些操作。

 如果希望使用一个现成的分布式锁库,可以选择 Redisson,它是基于 Redis 的高层次封装,提供了直接的分布式锁功能。

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

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

相关文章

机械硬盘与固态硬盘的区别-机械硬盘的未来在哪里?

随着近年来固态硬盘的技术成熟和成本的下探,固态硬盘(SSD)俨然有要取代传统机械硬盘(HDD)的趋势,但目前单位容量下机械硬盘每GB价格相比闪存还有5-7倍的优势,那么机械硬盘是否已经发展到极限&am…

06排序 + 查找(D1_排序(D1_基础学习))

目录 学习预热:基础知识 一、什么是排序 二、为什么要排序 三、排序的稳定性 四、排序稳定性的意义 五、排序分类方式 方式一:内外分类 方式二:比较分类 六、排序算法性能评估 1. 算法的时间复杂度 2. 算法的空间复杂度 七、知识小…

简讯:Rust 2024 edition and v1.85.0 已发布

详见 https://blog.rust-lang.org/2025/02/20/Rust-1.85.0.html 升级方法:rustup update stable

Python 错误和异常处理

目录 try-except块 例子: 输出: 捕获多种异常 例子: else和finally 例子: 输出: 自定义异常 例子: 输出: 好的,简单来说,错误和异常处理是编程中用来处理程序…

Linux系统使用Docker部署Geoserver并做数据挂载进行地图服务的发布和游览

文章目录 1、前提环境2、拉取geoserver镜像3、创建数据挂载目录4、 运行容器5、 测试使用(发布shp数据为服务)5.1、创建工作区5.2、添加数据存储5.3、发布图层5.4、服务游览 1、前提环境 部署环境:Linux,Centos7 ,Doc…

Innovus中快速获取timing path逻辑深度的golden脚本

在实际项目中我们经常会遇到一条timing path级数特别多,可能是一两页都翻不完。此时,我们大都需要手工去数这条path上到底有哪些是设计本身的逻辑,哪些是PR工具插入的buffer和inverter。 数字IC后端手把手培训教程 | Clock Gating相关clock …

Python爬虫实战:从零到一构建数据采集系统

文章目录 前言一、准备工作1.1 环境配置1.2 选择目标网站 二、爬虫实现步骤2.1 获取网页内容2.2 解析HTML2.3 数据保存 三、完整代码示例四、优化与扩展4.1 反爬应对策略4.2 动态页面处理4.3 数据可视化扩展 五、注意事项六、总结互动环节 前言 在大数据时代,数据采…

SpringBoot中实现限流和熔断功能

我们将使用Java的ScheduledExecutorService来实现一个简单的令牌桶算法(Token Bucket Algorithm),并结合一个自定义的服务类来处理第三方API调用。 1. 创建限流器 首先,创建一个简单的限流器类: import java.util.concurrent.*;public class SimpleRateLimiter {

如何使用Python快速开发一个带管理系统界面的网站-解析方案

如果你想用 Python 开发一个 管理系统界面 的网站,并且希望界面美观,可以考虑以下几个框架和库: 1. Streamlit(快速、简洁) 适合:数据分析、仪表盘、内部管理系统特点: 写法简单,类…

Git常见命令--助力开发

git常见命令: 创建初始化仓库: git 将文件提交到暂存区 git add 文件名 将文件提交到工作区 git commit -m "注释(例如这是发行的版本1)" 文件名 查看状态 如果暂存区没有文件被提交显示: $ git status On…

Java 前后端时间格式转换

在 Web 开发里,时间格式处理既常见又关键。由于前端和后端对时间的表示、处理方式存在差异,熟练掌握时间格式的转换方法就显得尤为重要。这篇文章会深入探讨 Java 前后端时间格式转换的相关知识,特别是 Java 时间转换的多种方式,其…

MySQL要点总结一

大纲 一.InnoDB的内存结构和更新机制 二.InnoDB的存储模型 三.并发事务原理 四.索引原理和索引优化 一.InnoDB的内存模型 1.SQL的执行流程 2.InnoDB的内存模型 3.Buffer Pool中的空闲缓存页与free链表 4.Buffer Pool中的脏页和flush链表 5.Buffer Pool通过LRU链表来淘…

常用网络工具分析(ping,tcpdump等)

写在前面 本文看下常用网络工具。 1:ping 1.1:用途 用于检验网络的连通性。 1.2:实战 在Linux环境中执行:ping www.sina.com.cn: [rootlocalhost ~]# ping www.sina.com.cn PING spool.grid.sinaedge.com (111.…

基于Flask的第七次人口普查数据分析系统的设计与实现

【Flask】基于Flask的第七次人口普查数据分析系统的设计与实现(完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 基于Flask的人口普查可视化分析系统 二、项目界面展示 登录/注册 首页/详情 …

11.Docker 之分布式仓库 Harbor

Docker 之分布式仓库 Harbor Docker 之分布式仓库 Harbor1. Harbor 组成2. 安装 Harbor Docker 之分布式仓库 Harbor Harbor 是一个用于存储和分发 Docker 镜像的企业级 Registry 服务器,由 VMware 开源,其通过添加一些企业必需的功能特性,例…

Zookeeper应用案例-分布式锁-实现思路

以下是具体实现代码 第一步:注册锁节点 第二步:获取锁节点,如果自己是最小的节点,就获取权限 第三步:拿到锁就开始自己的业务逻辑 第四步:业务逻辑好了就要释放这把锁 第五步:重新注册监听&…

Elasticsearch7.1.1 配置密码和SSL证书

生成SSL证书 ./elasticsearch-certutil ca -out config/certs/elastic-certificates.p12 -pass 我这里没有设置ssl证书密码,如果需要设置密码,需要再配置给elasticsearch 在之前的步骤中,如果我们对elastic-certificates.p12 文件配置了密码…

Linux(ubuntu) GPU CUDA 构建Docker镜像

一、创建Dockerfile FROM ubuntu:20.04#非交互式,以快速运行自动化任务或脚本,无需图形界面 ENV DEBIAN_FRONTENDnoninteractive# 安装基础工具 RUN apt-get update && apt-get install -y \curl \wget \git \build-essential \software-proper…

蓝桥杯——lcd显示

一:复制文件 从官方参考文件中复制相关文件,Src中的lcd.c,Inc中的lcd.h,fonts.h复制到自己创建的文件中 二:lcd初始化 在lcd.h中找到四个初始化函数,将其写到main文件中 三:写lcd显示函数 在…

【C++游戏开发-五子棋】

使用C开发五子棋游戏的详细实现方案,涵盖核心逻辑、界面设计和AI对战功能: 1. 项目结构 FiveChess/ ├── include/ │ ├── Board.h // 棋盘类 │ ├── Player.h // 玩家类 │ ├── AI.h // AI类 │ └── Game.h // 游戏主逻辑 ├── src/ …