使用分布式锁和乐观锁解决超卖问题

在电商、秒杀等高并发场景中,“超卖”问题指库存被过量扣减,导致实际库存不足。以下是使用 分布式锁乐观锁 解决超卖问题的原理与实现方案:


一、超卖问题的核心原因

多个并发请求同时读取库存余量,并在本地计算后发起写操作,导致实际扣减后的库存为负数。


二、解决方案 1:分布式锁

核心思想

通过 强制串行化 扣减库存操作,同一时间仅一个请求能处理库存。

实现步骤(以 Redis 为例):
  1. 获取锁
    使用 SET key uuid NX EX timeout 命令,确保原子性加锁。

    import redis
    r = redis.Redis()def acquire_lock(product_id, uuid, expire=10):key = f"lock:{product_id}"return r.set(key, uuid, nx=True, ex=expire)
    
  2. 扣减库存
    在锁的保护下执行库存操作:

    UPDATE inventory SET stock = stock - 1 WHERE product_id = 1 AND stock > 0;
    
  3. 释放锁
    使用 Lua 脚本保证原子性释放(避免误删其他请求的锁):

    if redis.call("get", KEYS[1]) == ARGV[1] thenreturn redis.call("del", KEYS[1])
    elsereturn 0
    end
    
优缺点
  • 优点:强一致性,逻辑简单。
  • 缺点:性能瓶颈(串行化)、锁失效风险(需合理设置超时时间)。

三、解决方案 2:乐观锁

核心思想

基于 版本号条件判断,在更新时校验数据未被修改,若冲突则重试或失败。

实现步骤(以 MySQL 为例):
  1. 查询库存与版本号

    SELECT stock, version FROM inventory WHERE product_id = 1;
    
  2. 更新库存(带条件)
    通过版本号或库存量确保原子性:

    -- 版本号方式
    UPDATE inventory 
    SET stock = stock - 1, version = version + 1 
    WHERE product_id = 1 AND version = {old_version} AND stock > 0;-- 条件判断方式(直接校验库存)
    UPDATE inventory 
    SET stock = stock - 1 
    WHERE product_id = 1 AND stock = {queried_stock} AND stock > 0;
    
  3. 检查更新结果
    若影响行数为 0,说明冲突,需重试或返回错误。

代码示例(伪代码):
def deduct_stock():retries = 3for _ in range(retries):# 查询库存和版本stock, version = db.query("SELECT stock, version FROM inventory WHERE product_id=1")if stock <= 0:return "库存不足"# 尝试更新rows = db.execute("UPDATE inventory SET stock=stock-1, version=version+1 ""WHERE product_id=1 AND version=%s AND stock>0",version)if rows > 0:return "成功"return "请重试"
优缺点
  • 优点:高并发性能好,无锁竞争。
  • 缺点:需处理重试逻辑,冲突频繁时性能下降。

四、方案对比与选型

方案适用场景性能复杂度一致性
分布式锁强一致性、低并发冲突强一致性
乐观锁高并发、冲突较少最终一致性

五、增强方案

  1. 结合缓存优化

    • 使用 Redis 预扣库存,异步同步到数据库。
    • 例如:先扣减 Redis 中的库存,再通过消息队列更新数据库。
  2. 库存分段

    • 将库存拆分为多个段(如 100 个库存拆为 10 段),每段独立加锁,提升并发度。
  3. 限流与降级

    • 使用令牌桶或漏桶算法限制请求流量,防止系统过载。

六、注意事项

  1. 分布式锁的可靠性
    • 推荐 Redlock 算法(多节点 Redis)或 ZooKeeper 实现高可用锁。
  2. 乐观锁的重试策略
    • 限制最大重试次数,避免无限循环。
  3. 事务隔离级别
    • 确保数据库隔离级别为 Read Committed 或以上,避免脏读。

通过合理选择锁机制并结合业务场景优化,可有效解决超卖问题。

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

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

相关文章

盛水最多的容器

本题有两种解法&#xff0c;一种是暴力解法&#xff0c;直接暴力枚举出所有的体积比较出最大的即可&#xff0c;但是时间复杂度达到n方。超出了限制&#xff0c;另一种解法就是利用单调性解法&#xff0c;我们着重介绍一下单调性解法。 单调性解法&#xff1a; 体积vh*w&…

操作系统概述(3)

批处理系统 1.单道批处理系统 单道批处理系统是成批地处理作用&#xff0c;并且始终只有一道作业在内存中的系统。优点&#xff1a;提高系统资源的利用率和系统吞吐量。缺点&#xff1a;系统中的资源得不到充分利用。 2.多道批处理系统 引入多道程序设计技术&#xff0c;是…

数字身份DID协议:如何用Solidity编写去中心化身份合约

本文提出基于以太坊的自主主权身份&#xff08;SSI&#xff09;实现方案&#xff0c;通过扩展ERC-734/ERC-735标准构建链上身份核心合约&#xff0c;支持可验证声明、多密钥轮换、属性隐私保护等特性。设计的三层架构体系将身份控制逻辑与数据存储分离&#xff0c;在测试网环境…

【目标检测】【深度学习】【Pytorch版本】YOLOV2模型算法详解

【目标检测】【深度学习】【Pytorch版本】YOLOV2模型算法详解 文章目录 【目标检测】【深度学习】【Pytorch版本】YOLOV2模型算法详解前言YOLOV2的模型结构YOLOV2模型的基本执行流程YOLOV2模型的网络参数YOLOV2模型的训练方式 YOLOV2的核心思想前向传播阶段反向传播阶段 总结 前…

第421场周赛:数组的最大因子得分、

Q1、数组的最大因子得分 1、题目描述 给你一个整数数组 nums。 因子得分 定义为数组所有元素的最小公倍数&#xff08;LCM&#xff09;与最大公约数&#xff08;GCD&#xff09;的 乘积。 在 最多 移除一个元素的情况下&#xff0c;返回 nums 的 最大因子得分。 注意&…

机器学习(神经网络基础篇)——个人理解篇5(梯度下降中遇到的问题)

在神经网络训练中&#xff0c;计算参数的梯度是关键步骤。numerical_gradient 方法旨在通过数值微分&#xff08;中心差分法&#xff09;计算损失函数对网络参数的梯度。然而&#xff0c;该方法的实现存在一个关键问题&#xff0c;导致梯度计算错误。 1、错误代码示例&#xf…

40常用控件_WindowFrame的影响

window frame 的影响 如果 widget 作为一个窗口(带有标题栏,最小化,最大化,关闭按钮),那么在计算尺寸和坐标的 时候就有两种算法.包含 window frame 和 不包含 window frame. 其中x(),y0,frameGeometry(), pos(),move() 都是按照包含 window frame 的方式来计算 的. 其中 geome…

Nginx搭建API网关服务教程-系统架构优化 API统一管理

超实用&#xff01;用Nginx搭建API网关服务&#xff0c;让你的系统架构更稳更强大&#xff01;&#x1f680; 亲们&#xff0c;今天来给大家种草一个超级实用的API网关搭建方案啦&#xff01;&#x1f440; 在如今的Web系统架构中&#xff0c;一个稳定、高性能、可扩展的API网…

USB设备老是提示有问题,如何解决

问题描述&#xff1a;有一台usb设备一旦不小心碰了下&#xff0c;后面就在右下角提示“无法识别的USB设备”“跟这台计算机连接的前一个USB设备0工作不正常&#xff0c;WIndows无法识别它”。我这个是明确知道那个设备&#xff0c;如果不知道也可以同样解决。 解决方法&#xf…

数据操作语言

一、DML的核心操作类型 1.添加数据(INSERT) (1)手动插入:逐行插入数据,适用于少量数据。 INSERT INTO 表名 (字段1, 字段2) VALUES (值1, 值2);(2)批量导入:通过外部文件导入数据,适用于大数据场景

【Python】案例:计算股票收益率和波动率

【Python】案例&#xff1a;计算股票收益率和波动率&#xff1a; 1、案例需求2、数据准备3、案例实现 1、案例需求 在分析股票数据时&#xff0c;我们需要从这些数据中得到一些关键指标进行评估&#xff0c;比如收益率、波动率&#xff0c;其中收益率又可以细分为简单收益率和…

geoserver搭建Docker一键直接安装并上传tif影像预览

geoserver搭建Docker一键直接安装 文章目录 geoserver搭建Docker一键直接安装前言一、Docker拉取Geoserver二、运行后使用geoserver进行数据管理进入geoserver调整语言登录geoserver上传一个tif影像建立工作空间并上传自己的tif数据建立图层预览 总结 前言 使用docker安装geos…

STM32看门狗应用实战:独立看门狗与窗口看门狗深度解析(下) | 零基础入门STM32第九十五步

主题内容教学目的/扩展视频看门狗什么是看门狗&#xff0c;原理分析&#xff0c;启动喂狗方法&#xff0c;读标志位。熟悉在程序里用看门狗。 师从洋桃电子&#xff0c;杜洋老师 &#x1f4d1;文章目录 一、看门狗应用架构分析1.1 系统监控流程图1.2 双看门狗应用场景对比 二、…

nacos集群启动问题

根据您的描述&#xff0c;Nacos集群只能启动两个节点&#xff0c;可能的原因和解决方法如下&#xff1a; 1. 集群配置问题 • 原因&#xff1a;cluster.conf文件中可能只配置了两个节点的地址&#xff0c;导致第三个节点无法加入集群。 • 解决方法&#xff1a; • 检查每个…

【C语言】跳台阶

相信你是最棒哒&#xff01;&#xff01;&#xff01; 一、题目描述 二、题目代码 1.斐波那契数列 2.DFS深度搜索 总结 一、题目描述 一只青蛙一次可以跳上1级台阶&#xff0c;也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法&#xff08;先后次序不同算不同的结果…

指纹浏览器技术架构解析:高并发批量注册业务的工程化实践——基于分布式指纹引擎与防关联策略的深度实现

一、技术背景与行业痛点 在跨境电商、广告投放、问卷调查等场景中&#xff0c;批量注册与多账号矩阵运营已成为刚需。然而&#xff0c;主流平台&#xff08;如亚马逊、Facebook、Google&#xff09;的风控系统通过浏览器指纹追踪&#xff08;Canvas/WebGL/WebRTC等&#xff09…

linux基础操作

一、系统目录知识 /bin&#xff1a; bin 是 Binaries (二进制文件) 的缩写, 这个目录存放着最经常使用的命令。 /boot&#xff1a; 这里存放的是启动 Linux 时使用的一些核心文件&#xff0c;包括一些连接文件以及镜像文件。 /dev &#xff1a; dev 是 Device(设备) 的缩写,…

源码分析之Leaflet图层控制控件Control.Layers实现原理

概述 本文将介绍Leaflet库中最后一个组件&#xff0c;即图层控制组件 Control.Layers。 源码实现 export var Layers Control.extend({options: {collapsed: true,position: "topright",autoZIndex: true,hideSingleBase: false,sortLayers: false,sortFunction:…

Element 使用 textarea 内容实现高度自适应

在 ElInput 组件的 type"textarea" 模式下&#xff0c;你可以使用 autosize 属性来实现内容高度自适应。当没有内容时默认显示 3 行&#xff0c;当有内容时根据内容动态调整高度。 代码&#xff1a; <el-form-item v-if"item.type textarea" :rules&…

Java技术生态前沿洞察:虚拟线程引领并发革命,框架创新赋能云原生时代

Java技术生态正迎来新一轮变革浪潮。虚拟线程的落地成为高并发编程范式转折点&#xff0c;其极低资源开销特性在电商秒杀场景中展现出3倍吞吐量提升&#xff0c;彻底改写传统线程模型性能边界。Spring Boot 3.2原生支持虚拟线程&#xff0c;结合Observation API与HTTP客户端优化…