miqiu的分布式锁(二):实战——用JMeter验证JVM锁能否解决MySQL超卖问题

ops/2025/2/27 14:20:31/

miqiu的分布式锁二:实战——用JMeter验证JVM锁能否解决MySQL超卖问题

实验背景

在秒杀场景中,超卖问题是典型的并发编程挑战。本文通过JMeter压测工具,验证基于JVM的两种锁机制(synchronized/ReentrantLock)对MySQL库存操作的防护效果。


实验一:内存库存操作验证

1.1 无锁场景

public void deduct() {stock.setStock(stock.getStock() - 1);System.out.println("库存余量:" + stock.getStock());
}

压测结果(100线程×50次循环):

  • 平均响应时间:3ms
  • 吞吐量:2217/sec
  • 最终库存:-89(严重超卖)

无锁压测报告


1.2 synchronized锁方案

public synchronized void deduct() {stock.setStock(stock.getStock() - 1);System.out.println("库存余量:" + stock.getStock());
}

压测结果对比

  • 平均响应时间 ↗ 25ms(733%增长)
  • 吞吐量 ↘ 396/sec(82%下降)
  • 最终库存 ✅ 0(完美解决)

同步锁压测报告


1.3 ReentrantLock方案

private final ReentrantLock lock = new ReentrantLock();public void deduct() {lock.lock();try {stock.setStock(stock.getStock() - 1);System.out.println("库存余量:" + stock.getStock());} finally {lock.unlock();}
}

性能表现

  • 平均响应时间:22ms
  • 吞吐量:440/sec
  • 最终库存 ✅ 0

重入锁压测报告


实验二:真实MySQL库存操作

2.1 无锁数据库操作

public void deduct() {Stock stock = stockMapper.selectByProductCode("1001");if(stock != null && stock.getCount() > 0) {stock.setCount(stock.getCount() - 1);stockMapper.updateById(stock);}
}

压测结果

  • 平均响应时间:249ms
  • 吞吐量:394/sec
  • 最终库存:4900(严重超卖)

数据库无锁压测


2.2 ReentrantLock防护方案

private final ReentrantLock lock = new ReentrantLock();public void deduct() {lock.lock();try {Stock stock = stockMapper.selectByProductCode("1001");if(stock != null && stock.getCount() > 0) {stock.setCount(stock.getCount() - 1);stockMapper.updateById(stock);}} finally {lock.unlock();}
}

验证结果

  • 平均响应时间 ↗ 623ms(151%增长)
  • 吞吐量 ↘ 158/sec(60%下降)
  • 最终库存 ✅ 0(正确扣减)

数据库锁压测


关键结论

  1. 防护有效性
    JVM级锁能有效解决单机部署下的超卖问题,确保库存操作的原子性

  2. 性能代价
    synchronized/ReentrantLock均造成吞吐量显著下降,响应时间成倍增加

  3. 架构局限

    • 仅适用于单服务实例场景
    • 分布式部署时不同JVM实例的锁相互不可见
    • 数据库连接池耗尽风险(长时间持锁)

后续方向

通过本实验验证了JVM锁的单机有效性,但分布式场景需要更强大的锁机制。下一篇将研究jvm锁的失效情况


http://www.ppmy.cn/ops/161697.html

相关文章

PnP——根据3D与2d图片估计相机运动

引入 当知道n个3D空间点及其投影位置和2d像素点时,如何估计相机的位姿。PnP(Perspective-n-Point) 是求解3D到2D点对运动的方法。 直接线性变换(DLT) 问题描述 已知一组3D点 P i ( X i , Y i , Z i , 1 ) ⊤ \mathbf{P}_i (X_i, Y_i, …

深入浅出深度学习中的BatchSize

一、Batch Size 的核心作用 Batch Size 决定了模型每次更新参数时使用的样本数量。直接影响以下方面: 梯度计算的准确性: 大 Batch 的梯度是多个样本的平均,更接近“真实梯度”(整个数据集的梯度方向)。小 Batch 的梯…

HarmonyOS学习第7天: 文本组件点亮界面的文字魔法棒

一、引言 在 HarmonyOS 那丰富多彩的系统界面中,从简洁直观的应用图标,到交互流畅的操作菜单,再到生动形象的图文展示,每一处细节都经过精心雕琢,为用户带来了独特而美妙的视觉与交互体验。而在这琳琅满目的界面元素中…

Attu向量数据库管理工具部署

Milvus 官网自带UI样式太丑,且功能鸡勒,我们可以使用attu 管理工具代替, docker run -p 8000:3000 -e MILVUS_URL{milvus server IP}:19530 zilliz/attu:v2.5 翻墙下载镜像 zilliz/attu:v2.5 docker pull zilliz/attu:v2.5docker save -…

下载commons-io-jar 2.6版本

Commons IO – Download Apache Commons IO 打开官网,如下图所示: 点击archives 找到2.6版本,进行下载 这是解压后的

Spring Boot @Component注解介绍

Component 是 Spring 中的一个核心注解,用于声明一个类为 Spring 管理的组件(Bean)。它是一个通用的注解,可以用于任何层次的类(如服务层、控制器层、持久层等)。通过 Component 注解,Spring 会…

【Qt之QQuickWidget】QML嵌入QWidget中

由于我项目开始使用Widgets,换公司后直接使用QML开发,没有了解过如何实现widget到qml过渡,恰逢面试时遇到一家公司希望从widget迁移到qml开发,询问相关实现,一时语塞,很尴尬,粗略研究并总结下。 对qwidget嵌…

视频时代,图文未来如何发展

视频时代,图文未来如何发展 在数字传播的技术奇点时代,视频媒介已构建起覆盖全球的认知引力场。当TikTok的算法瀑布流与B站的知识图谱持续重塑人类感知界面时,我们正目睹着视听语言对信息传播范式的革命性重构——这种以帧率为单位的叙事革新…