当前位置: 首页 > article >正文

基于 Redis 实现分布式锁:原理及注意事项

文章目录

  • 基于 Redis 实现分布式锁:原理及注意事项
    • 基于 Redis 实现分布式锁的原理
    • Redis 分布式锁的过期时间和锁续期机制
    • 如何防止锁被其他 goroutine 删除?
    • Redis 分布式锁存在的单点故障问题:基于 RedLock 的解决方案
    • 高并发场景中 Redis 分布式锁的优化
      • 分段锁(Shared Lock)
      • 锁的细粒度化
    • 如何确定 Redis 分布式锁的过期时间?
      • 分级设置策略
      • 动态调整

基于 Redis 实现分布式锁:原理及注意事项

在这里插入图片描述

基于 Redis 实现分布式锁的原理

画板

重点在于:通过 SETNX来确保 Key 的不可重入。SETNX确保了GETSET方法的原子性。

Redis 分布式锁的过期时间和锁续期机制

第二个问题在于,如果服务实例在获取锁之后挂掉了,会导致删除锁的逻辑执行不到,这个时候应该怎么办?答案是可以为 Redis 分布式锁设置一个过期时间,过期之后锁自动删除,可以解决死锁问题

由此引发的另一个问题是,如果业务逻辑还没有执行完毕,锁就过期了,其他服务实例就可以获取锁了,这个时候该怎么办?解决办法是:

  • 在锁过期之前,刷新一下锁的过期时间。具体实现上,Go 当中的 Redsync 源码会使用 Lua 脚本原子性地判断当前 Key 在 Redis 缓存中的 Value 是否和当前的服务实例设置的 Value 一致(这个 Value 应该是一个标识服务实例的 Unique_ID)。使用 Lua 可以确保原子性,使得锁续期的过程不会被中断。
  • 需要自己去启动一个 goroutine 完成锁续期的工作。为什么不自动续期呢?原因是锁续期的接口可能会带来负面影响:比如其中的一个服务 hung 住了(一直没有执行完,可能是因为硬件的原因),但是一直进行锁续期,会导致其他服务实例永远获取不到锁。所以说锁续期不是默认的,由用户自行选择。

如何防止锁被其他 goroutine 删除?

Redis 分布式锁需要解决的问题:

  1. 互斥性:通过 SETNX 来解决;
  2. 死锁:通过设置过期时间 PX timeout 来解决;
  3. 安全性:锁只应该由持有这把锁的实例删除,而不能被其他实例删除

如何确保 Redis 分布式锁的安全性?通过服务实例加锁时设置的 Value 值来确定。这个 Value 应该只有设置了锁的那个服务实例(比如 goroutine)知道。Go 的 redsync 分布式锁库在加锁时会自动生成一个 unique_id。

Redis 分布式锁存在的单点故障问题:基于 RedLock 的解决方案

即使确保了互斥性与安全性,并通过设置过期时间解决了死锁问题,Redis 分布式锁仍然存在单点故障问题。

一个典型的场景就是:在 Redis 主从集群当中,仅有 Master 节点可以处理写请求,其他若干个 Slave 节点只能处理读请求,写操作依赖 Master 节点的同步(为了确保性能,很有可能是异步的)。存在的问题是,如果某个服务实例向该 Redis 集群申请加分布式锁,加锁之后 Master 节点突然宕机了,此时 Sentinel 节点需要推选 Slave 节点成为新的 Master,假如此时 Master 节点加锁的信息还没有同步到 Slave 节点,就会导致新推选出的 Master 节点(之前的 Slave 节点)不知道服务实例的加锁信息,导致锁可被重入。

解决上述问题的方法是通过 RedLock 来为服务实例提供分布式锁服务。具体来说,RedLock 由 N(奇数,确保「多数派」的产生)个 Redis 主节点(可以是 Redis 主从集群,可以是 Redis 单机实例,比如有 5 个 Redis 主节点,那么可以是 3 个 Redis 主从集群 + 2 个 Redis 单机实例。需要特别注意的是,Redis 分片集群不能用于 RedLock)组成,客户端请求加锁时,需要同时向所以 Redis 主节点并发地请求加锁,当多数(N / 2 + 1)Redis 主节点同意加锁请求时,客户端才算加锁成功,否则加锁失败。如果加锁失败,客户端需要同时向所以 Redis 主节点发送锁撤销的请求。

高并发场景中 Redis 分布式锁的优化

现在有一个「商品秒杀」的业务场景,针对单一商品,多个服务实例在下单时,通常需要使用分布式锁来保证商品不被「超卖」。但是「加锁」仍然是强行将「并发改为串行」,在高 QPS 场景下性能仍然不够好,请问在这种情况下,应该对分布式锁进行哪些优化?

分段锁(Shared Lock)

可以将单一商品库存分成多个段,每个段的 Key 各不相同,也就是 Redis 分布式锁在加锁时加锁的对象各不相同。通过某种调度算法均匀地将加锁请求分散到不同的 Key 上,每个 Key 使用独立的锁,可以提高并发度。

# 假设将库存分成10段
segments = 10
segment_id = user_id % segments  # 根据用户ID或其他策略分配段
lock_key = f"product_{product_id}_segment_{segment_id}"# 获取分段锁
if acquire_lock(lock_key):try:# 处理分段库存finally:release_lock(lock_key)

锁的细粒度化

根据业务场景设计更加细粒度的锁:

  • 按用户 ID 加锁(防止同一用户的重复请求);
  • 按商品 ID + 库存分段加锁;
  • 按区域/服务器加锁。

如何确定 Redis 分布式锁的过期时间?

分级设置策略

对于不同类型的操作,应该考虑设置不同的锁过期时间,比如对于内存操作,可以设置为500ms,而对于数据库事务,则应该设置为2s并加入锁续期机制以确保长事务的执行。

动态调整

可以根据系统的实时负载情况动态调整锁过期时间,比如在系统高负载时降低锁过期时间。

相关文章:

基于 Redis 实现分布式锁:原理及注意事项

文章目录 基于 Redis 实现分布式锁:原理及注意事项基于 Redis 实现分布式锁的原理Redis 分布式锁的过期时间和锁续期机制如何防止锁被其他 goroutine 删除?Redis 分布式锁存在的单点故障问题:基于 RedLock 的解决方案高并发场景中 Redis 分布…...

手机设备多?怎样设置IP保证不关联

在移动互联网时代,多设备运营(如电商、游戏工作室、社交媒体矩阵)常面临IP关联风险,轻则账号受限,重则封禁。以下提供6种高效设置独立IP的方法,结合技术原理与实操建议,助您打造稳定合规的运营环…...

Linux 中常见的安全与权限机制

Linux 中常见的安全与权限机制主要包括以下几类,从文件系统权限到系统级访问控制,构建了多层次的安全保障体系。 🔐 一、文件权限与用户管理 1. 基本权限(rwx) r(read):读取文件内…...

Golang|单例模式

单例模式定义:在程序运行期间,某个结构体只创建一个实例。适用场景:如数据库连接池,在整个程序运行期间只需要一个连接池实例。 方案一:通过加锁的方式,如读写锁,确保在并发情况下只创建一个实…...

哈尔滨工业大学计算机系统大作业程序人生-Hello’s P2P

摘 要 文章以C语言程序设计经典案例hello.c为研究对象,系统解析程序在计算机系统中的完整生命周期。剖析源代码通过预处理、编译、汇编、链接四阶段演化为可执行目标程序的编译系统工作机制,继而从进程视角揭示程序运行时计算机体系结构的协同运作&…...

小程序定制开发:从需求到落地,打造企业专属数字化入口

在移动互联网时代,小程序已成为企业连接用户的核心载体。定制开发因能深度匹配企业需求,正成为各行业数字化转型的优选方案。以下从优势、流程、技术、案例四方面展开,助你快速掌握关键要点。 一、定制开发的核心优势 1. 高度个性化&#x…...

【C/C++】基于 Docker 容器运行的 Kafka + C++ 练手项目

文章目录 基于 Docker 容器运行的 Kafka C 练手项目1 项目目的2 项目框架3 代码4 编译运行5 功能与接口说明5.1 Producer 接口:producer.cpp关键调用流程参数说明 5.2 Consumer 接口:consumer.cpp关键调用流程消费流程中注意 5.3 工程技术点 基于 Docke…...

Linux系统管理与编程24:基础条件准备-混搭“本地+阿里云”yum源

兰生幽谷,不为莫服而不芳; 君子行义,不为莫知而止休。 1.添加宿主机共享文件夹 Linux虚拟机可以和宿主机共享文件夹,这样有利于工具文件的共享。具体操作如下: 1)vmware workstation共享文件夹 虚拟机…...

新一代Python管理UV完全使用指南|附实际体验与效果对比

简介 uv是新一代的Python项目管理工具,具备开发一个完整项目的所有功能点: 功能点描述包管理完全替代pip的功能,支持包的安装、升级、卸载等操作虚拟环境管理内置虚拟环境创建和管理,无需额外安装virtualenv或venv依赖解析与锁定…...

如何在 Windows 10 PC 上获取 iPhone短信

您可以轻松地将媒体数据从 iPhone 传输到 Windows 计算机,并直接访问计算机上的数据。但是,您可以在 Windows 10 PC 上接收 iPhone 短信吗?有什么功能或工具支持它吗?如果您发现在 Windows 10 PC 上接收 iPhone 消息很困难&#x…...

STM32程序运行不了,仿真功能也异常,连断点和复位都异常了

先检查有没有出现复位引脚rst短接0的情况 在检查是否出现明明没配置该外设你却偏偏要使用的情况,比如串口没配置你却偏要发送,引脚没配置你却偏要读取 这几个可能最好的办法就是从开头一行一行注释再运行看看能不能跑起来 还可以用以下方法 检查硬…...

Linux 系统中的软链接与硬链接

目录 一、什么是软链接? 1. 创建软链接 2. 软链接的特性 3. 软链接的用途 二、什么是硬链接? 1. 创建硬链接 2. 硬链接的特性 3. 硬链接的用途 4. 目录硬链接的特殊性 ​编辑 三、软链接与硬链接的区别 1. inode 编号 2. 路径依赖 3. 删除行…...

Python爬虫第22节- 结合Selenium识别滑动验证码实战

目录 一、引言 二、滑动验证码原理与反爬机制 2.1 验证码原理 2.2 反爬机制 三、工程实战:滑动验证码识别全流程 3.1 工程准备 3.1.1 环境依赖 3.1.2 目标网站与验证码识别案例 3.2 核心破解流程 3.2.1 自动化打开网页与登录 3.2.2 获取验证码图片&#…...

【C/C++】chrono简单使用场景

chrono使用场景举例 1 输出格式化字符串 示例代码 auto now std::chrono::system_clock::now(); auto t std::chrono::system_clock::to_time_t(now); auto ms std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;std::ostrin…...

Escrcpy(安卓手机投屏软件) v1.29.6 中文绿色版

在数字设备日益普及的今天&#xff0c;用户对于设备的控制和管理需求也在不断增加。对于Android设备用户来说&#xff0c;Escrcpy这款强大的工具无疑是一个福音。它不仅提供了直观的图形化界面&#xff0c;让用户能够轻松显示和控制自己的Android设备&#xff0c;还以完全免费开…...

Oracle MOVE ONLINE 实现原理

Oracle MOVE ONLINE 实现原理 Oracle 的 MOVE ONLINE 操作是一种在线重组表的技术&#xff0c;允许在不中断业务的情况下重新组织表数据。以下是其实现原理的详细分析&#xff1a; 基本概念 MOVE ONLINE 是 Oracle 12c 引入的特性&#xff0c;用于替代传统的 ALTER TABLE ..…...

Linux:深入理解网络层

网络层在复杂的网络环境中确定一个合适的路径.传输到指定的网络中 一、网络层的理解 问题1&#xff1a;为什么要有网络层的概念呢&#xff1f;&#xff1f; ——>我们先来讲一个故事&#xff1a; 假设我在学校里被誉为数学大神&#xff0c;是因为我的数学有考满分的能力&…...

【设计模式】简单工厂模式,工厂模式,抽象工厂模式,单例,代理,go案例区分总结

工厂模式三种类型&#xff1a; 一、简单工厂模式&#xff08;Simple Factory&#xff09; 定义&#xff1a; 用一个工厂类&#xff0c;根据传入的参数决定创建哪一种具体产品类实例。 面试说法&#xff1a; 由一个统一的工厂创建所有对象&#xff0c;增加新产品时需要修改工…...

Linux_编辑器Vim基本使用

✨✨ 欢迎大家来到小伞的大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;LInux_st 小伞的主页&#xff1a;xiaosan_blog 制作不易&#xff01;点个赞吧&#xff01;&#xff01;谢谢喵&#xff01;&a…...

vue展示修改前后对比,并显示修改标注diff

动态父组件 <template><el-buttontype"primary"size"small"plainclick"showDiffDialog(subItem)">查看修改内容</el-button><TextDiffDialogv-model:visible"diffDialogVisible":before"currentDiffItem?.…...

LiveWallpaperMacOS:让你的 Mac 桌面动起来

随着桌面美化需求的不断提升,用户对于桌面壁纸的要求已经不再局限于静态图片。越来越多的 Mac 用户希望桌面能像 Windows 一样,拥有动态壁纸,展现个性、提升体验。LiveWallpaperMacOS 正是这样一款让你的 Mac 桌面焕发活力的开源项目。 本文将详细介绍 LiveWallpaperMacOS …...

[预训练]Encoder-only架构的预训练任务核心机制

原创文章1FFN前馈网络与激活函数技术解析&#xff1a;Transformer模型中的关键模块2Transformer掩码技术全解析&#xff1a;分类、原理与应用场景3【大模型技术】Attention注意力机制详解一4Transformer核心技术解析LCPO方法&#xff1a;精准控制推理长度的新突破5Transformer模…...

07-后端Web实战(部门管理)

5. 修改部门 对于任何业务的修改功能来说&#xff0c;一般都会分为两步进行&#xff1a;查询回显、修改数据。 5.1 查询回显 5.1.1 需求 当我们点击 "编辑" 的时候&#xff0c;需要根据ID查询部门数据&#xff0c;然后用于页面回显展示。 5.1.2 接口描述 参照参照…...

mysql ACID 原理

序言&#xff1a;ACID 是一组数据库设计原则&#xff0c;他是业务数据和关键业务程序的可靠性保障。 1、atomicity&#xff08;原子性&#xff09; 依赖如下能力 autocommit commit rollback2、一致性 2.1 double write buffer 1、定义&#xff1a;double write buffer 是…...

[Rust_1] 环境配置 | vs golang | 程序运行 | 包管理

目录 Rust 环境安装 GoLang和Rust 关于Go 关于Rust Rust vs. Go&#xff0c;优缺点 GoLang的优点 GoLang的缺点 Rust的优点 Rust的缺点 数据告诉我们什么&#xff1f; Rust和Go的主要区别 (1) 性能 (2) 并发性 (3) 内存安全性 (4) 开发速度 (5) 开发者体验 Ru…...

二十五、面向对象底层逻辑-SpringMVC九大组件之HandlerMapping接口设计

一、引言&#xff1a;MVC架构的交通枢纽 在Spring MVC框架中&#xff0c;HandlerMapping接口扮演着"请求导航仪"的关键角色&#xff0c;它决定了HTTP请求如何被路由到对应的Controller处理器。作为MVC模式的核心组件之一&#xff0c;HandlerMapping在请求处理的生命…...

构建安全高效的邮件网关ngx_mail_ssl_module

一、快速上手&#xff1a;最小配置示例 worker_processes auto;mail {server {# 监听 IMAP over TLSlisten 993 ssl;protocol imap;# TLS 协议与密码套件ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers HIGH:!aNULL:!MD5;# 证书与私钥ssl_…...

HUAWEI交换机配置镜像口验证(eNSP)

技术术语&#xff1a; 流量观察口&#xff1a;就是我们常说的镜像口&#xff0c;被观察的流量的引流目的端口 流量源端口&#xff1a;企业生产端口&#xff0c;作为观察口观察对象。 命令介绍&#xff1a; [核心交换机]observe-port [观察端口ID或编号&#xff08;数字&am…...

前端vue3实现图片懒加载

场景和指令用法 场景:电商网站的首页通常会很长&#xff0c;用户不一定能访问到页面靠下面的图片&#xff0c;这类图片通过懒加载优化手段可以做到只有进入视口区域才发送图片请求 核心原理:图片进入视口才发送资源请求 首先&#xff1a;我们需要定义一个全局的指令&#x…...

网站每天几点更新,更新频率是否影响网站收录

1. 每天几点更新网站最合适&#xff1f;总怕时间选错影响收录&#xff1f; 刚开始搞网站的时候&#xff0c;是不是老纠结啥时候更新合适&#xff1f;早上刚上班&#xff1f;半夜没人的时候&#xff1f;选不对时间&#xff0c;总担心搜索引擎爬虫来了没抓到新内容&#xff0c;影…...