redis实战---分布式锁--单机篇
redis分布式锁
- 故事背景
- 什么是Redis分布式锁
- 业务场景
- 未加任何锁的代码
- 单机情况下JVM级别加锁
- 多服务部署
- 总结提升
故事背景
本篇文章是redis实战系列的第二篇文章。本章的主要内容是Redis分布式锁的相关知识。本篇文章将告诉你什么是分布式锁,结合一个业务场景,先带大家看看,单机上是如何实现锁功能的。学完本篇,你可以了解到什么是锁,为什么要加锁。
什么是Redis分布式锁
Redis分布式锁是一种基于Redis实现的分布式锁机制,它可以保证在分布式环境中,同一时刻只有一个客户端能够获取到锁,从而避免了多个客户端同时对同一资源进行修改的问题。

接下来我将结合一个秒杀的例子讲述如果实现Redis的分布式锁。
业务场景
秒杀场景是一个非常经典的需要使用锁的场景。
假设有一个商品限时秒杀的业务场景,多个用户同时在秒杀开始时间内尝试购买该商品,但是该商品数量有限,只有一定数量的用户可以购买成功,其他用户则购买失败。
为了保证秒杀的公平性与真确性,这个时候我们就要通过锁来对商品的数量进行访问
未加任何锁的代码
结合上面的业务场景,我们来先来实现一个未加任何锁的代码,简单实现一下这个小需求:
- 首先在redis里添加了 key值为 stock value值 为 200 的数据,模拟我们要秒杀的商品数量为200

2.编写业务逻辑代码
@RestController
@RequestMapping("/test")
public class IndexController {// 自动注入 StringRedisTemplate 对象@Autowiredprivate StringRedisTemplate stringRedisTemplate;// 处理 HTTP GET 请求路径是 /test/lock@GetMapping("lock")public String deductStock() {// 获取当前库存String stock1 = stringRedisTemplate.opsForValue().get("stock");if( stock1 == null){System.out.println("秒杀未开始");return "end";}int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));if (stock > 0) {// 扣减库存int realStock = stock - 1;// 更新库存stringRedisTemplate.opsForValue().set("stock", realStock + "");System.out.println("扣减成功,剩余的库存为:" + realStock);} else {System.out.println("扣减失败,库存不足");}return "end";}}
上述是根据我们的业务进行的一个简单的实现,在这个实现里,未对代码进行加锁。这段代码将会出现很经典的超卖问题。我们来压测一下接口,看一下效果
3. 接口压测,模拟并发

在这里我们使用的ApiPost进行一键压测。让我们一起来看一下结果吧

我们发现,50个请求进来之后,如果是正常的情况下,是应该减少50个库存,每个请求获得1个商品。可以根据结果看,我们的50个请求获得了5个商品。同一个商品卖给了多个用户。列如 195号商品同时卖给了10个人。
那么我们该如何去解决这个问题呢?
单机情况下JVM级别加锁
首先我们来看一下,如果是单机(项目只部署在一台机器上),如何给我们的代码加锁,解决上述问题。
使用 synchronized 进行jvm级别加锁。
- 代码
synchronized (this){// 获取当前库存String stock1 = stringRedisTemplate.opsForValue().get("stock");if( stock1 == null){System.out.println("秒杀未开始");return "end";}int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));if (stock > 0) {// 扣减库存int realStock = stock - 1;// 更新库存stringRedisTemplate.opsForValue().set("stock", realStock + "");System.out.println("扣减成功,剩余的库存为:" + realStock);} else {System.out.println("扣减失败,库存不足");}}
代码非常的简单,使用 synchronized 关键字,将我们的业务逻辑进行包裹即可。
synchronized,保证同一时刻只有一个线程执行被synchronized修饰的代码块或方法,从而避免多个线程同时对共享资源进行修改而导致的数据不一致的问题。
2. 运行结果

从结果上来看,通过synchronized 可以在jvm级别上进行上锁。但是我们实际的生产环境中,很少有部署单机服务的。如果我们部署了多个服务,那么通过synchronized 是肯定无法影响另一条机器上的请求的。
多服务部署

假设我们,部署了两个服务,部署在tomcat1和tomcat2上,使用nginx做负载。此时仅仅通过synchronized 只能保持 tomcat1自己本身。tomcat2自己本身的数据被锁住。如果两个服务同时提供服务,仍然会产生我们上述的超卖问题。
总结提升
本文我们主要讲了锁的概念,为什么要加锁,单机上jvm级别的加锁,多服务部署的话,我们现在的代码存在的问题。接下来我会讲解如何解决我们这次遗留的问题,在分布式环境下,如何加锁,如何解决可能会存在的问题。
专栏地址
相关文章:
redis实战---分布式锁--单机篇
redis分布式锁故事背景什么是Redis分布式锁业务场景未加任何锁的代码单机情况下JVM级别加锁多服务部署总结提升故事背景 本篇文章是redis实战系列的第二篇文章。本章的主要内容是Redis分布式锁的相关知识。本篇文章将告诉你什么是分布式锁,结合一个业务场景&#x…...
Java正则表达式
Java 正则表达式 文章目录Java 正则表达式捕获组正则表达式语法Matcher 类的方法索引方法查找方法替换方法start 和 end 方法matches 和 lookingAt 方法replaceFirst 和 replaceAll 方法appendReplacement 和 appendTail 方法PatternSyntaxException 类的方法正则表达式是对字符…...
MySQL数据库之——高级[进阶]SQL语句(二)正则表达式和存储过程
文章目录一、正则表达式(REGEXP)1、正则表达式匹配符2、语法二、存储过程1、概述2、优点3、 创建、调用、查看和删除存储过程4、存储过程的控制语句一、正则表达式(REGEXP) 1、正则表达式匹配符 2、语法 SELECT 选项 FROM 表名 …...
Python基于周立功盒子的二次开发的准备工作
Python基于周立功盒子的二次开发的准备工作 一、基本介绍 基于周立功的二次开发是python通过调用zlgcan.dll,来实现CAN卡的通讯收发报文的,在python中通过ctypes模块调用c++动态库的接口函数(zlgcan.dll),我们需要根据我的电脑选择相对应版本的dll,比如64位的操…...
2023年PMP考生|考前必练全真模拟题分享,附答案解析
“日日行,不怕千万里;常常做,不怕千万事。”每日五题,备考无压力! 1、敏捷项目以价值为驱动交付,确定好所有待办事项的价值进而去制造可交付成果。那么在整个敏捷项目周期中,衡量团队交付的可交…...
Python入门教程+项目实战-7.1节: 条件控制结构
目录 7.1.1 理解条件控制 7.1.2 if,elif,else 7.1.3 条件表达式 7.1.4 条件控制可以嵌套 7.1.5 if语句的三元运算 7.1.6 系统学习python 7.1.1 理解条件控制 在日常生活中,我们常喜欢说如果, "如果怎么样,那么就会怎么样"。"如果&…...
【机器学习】P4 特征缩放与学习率
这里写自定义目录标题特征缩放标准化归一化平均值归一化收敛学习率特征缩放 特征缩放(Feature scaling)是一种数据预处理技术,它用于将不同尺度的特征值缩放到相同的范围内,以便更好地应用于机器学习算法中。在不进行特征缩放的情…...
《Python编程:从入门到实战》(第2版)学习笔记 第11章 测试代码
【写在前面】为进一步提高自己的python代码能力,打算把几本经典书籍重新过一遍,形成系统的知识体系,同时适当记录一些学习笔记,我尽量及时更新!先从经典的《Python编程:从入门到实战》书籍开始吧。有问题欢…...
SpringBoot(1)基础入门
SpringBoot基础入门SpringBoot项目创建方式Idea创建SpringBoot官网创建基于阿里云创建项目手工搭建SpringBoot启动parentstarter引导类内嵌tomcat基础配置属性配置配置文件分类yaml文件yaml数据读取整合第三方技术整合JUnit整合MyBatis整合Mybatis-Plus整合DruidSpringBoot是由…...
利用Flow Simulation快速经济高效地解决传热难题
几乎一切事物都会经历某种程度的发热或冷却,而且对于许多产品来说,热管理已成为避免过度发热和实现功能正常运行的一个关键要求。能够有效解决传热问题的制造商将会在竞争中占有明显的优势。利用一个简单易用的流体分析应用程序 SOLIDWORKS Flow Simulat…...
揭开二维码背后的神秘面纱用二维码识别 API 就够了
写在前面 二维码(QR code)已经成为现代生活中不可或缺的一部分。二维码具有可靠性、快速识别、易于存储等优点,因此在广泛应用于支付、门票、社交网络、广告等方面。但是,对于大多数人来说,二维码背后的编码方式是完全…...
系统分析——系统构建最重要的一环
🌟所属专栏:信息系统分析与设计 🐔作者简介:rchjr——五带信管菜只因一枚 😮前言:该系列将持续更新信息系统分析与设计课程的相关学习笔记,欢迎和我一样的小白订阅,一起学习共同进步…...
第1-第20个高级shell程序
高级shell脚本 1.使用Shell脚本批量修改文件名 #!/bin/bash for fi lein$(ls*.txt) do mv $file${file%%.*}.md done2.统计一个文本文件中某个单词出现的次数 #!/bin/bashword"example" count0 whilereadline do forwin$line do if["$w""$word&qu…...
【致敬嵌入式攻城狮第2期活动预热征文】学习安排
文章目录「 致敬未来的攻城狮计划 」——学习计划前言学习计划🚗单片机理论实践🚗学业阅读计划「 致敬未来的攻城狮计划 」——学习计划 🚀🚀开启攻城狮的成长之旅!这是我参与的由 CSDN博客专家 架构师李肯和 瑞萨MCU …...
035:cesium加载KML文件,显示图形
第035个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中加载KML文件, 显示图形。 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共83行)相关API参考:专栏目标示例效果 配置方式 1)查看基础设置:https:/…...
随想录Day42--动态规划: 416. 分割等和子集(终于吃下01背包了)
今天只有1道题,属于动态规划的01背包问题的应用。首先理解一下动态规划的01背包问题。推荐一个视频,动态规划DP0-1背包,这是我认为讲得最为通透的。很多讲解动态背包问题的,一上来就画二维表格,遍历背包或者遍历容量&a…...
字节跳动软件测试岗,前两面过了,第三面被面试官吊打,结局我哭了
阎王易见,小鬼难缠。我一直相信这个世界上好人居多,但是也没想到自己也会在阴沟里翻船。我感觉自己被字节跳动的HR坑了。 在这里,我只想告诫大家,offer一定要拿到自己的手里才是真的,口头offer都是不牢靠的࿰…...
bitlocker 笔记
介绍 bitlocker是windows自带的磁盘加密工具,win10专业版是可以使用的,其他家庭版本可能没有这个功能。有点类似与wd security。 功能 加密磁盘,当磁盘物理丢失时,防止磁盘中的数据泄露。举个例子,移动硬盘被偷&…...
Linux 压缩与解压命令
一、常见的压缩文件扩展名 1、*.Z compress程序压缩的文件 2、*.gz gzip程序压缩的文件 3、.tar.gz tar程序打包的文件,其中经过gzip的压缩 4、.tar tar程序打包的数据,并没有压缩过 5、.bz2 bzip2程序压缩的文件 6、.tar.bz2 tar程序打包的文件&a…...
python global函数用法及常用的 global函数代码
Python中的 global函数是用于在程序中定义变量的函数,在我们实际的开发中,我们可能会用到 global函数来定义变量,但是我们在这里就不具体介绍它的用法了。 global函数定义变量的方法: global函数使用参数a来指定变量在程序中的地址…...
彻底告别桌面混乱:NoFences桌面分区工具终极解决方案
彻底告别桌面混乱:NoFences桌面分区工具终极解决方案 【免费下载链接】NoFences 🚧 Open Source Stardock Fences alternative 项目地址: https://gitcode.com/gh_mirrors/no/NoFences 还在为Windows桌面上杂乱无章的图标而烦恼吗?每天…...
借助Taotoken用量看板,精细化分析团队大模型API消耗趋势
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 借助Taotoken用量看板,精细化分析团队大模型API消耗趋势 对于团队管理者或项目负责人而言,大模型API的调用…...
矩阵键盘原理与实战:从扫描算法到Arduino/CircuitPython驱动指南
1. 项目概述:为什么我们需要矩阵键盘? 在嵌入式项目里,给设备加几个按钮是再常见不过的需求。但如果你需要10个、12个甚至16个独立的按键呢?按照传统思路,一个按键对应一个微控制器的数字输入引脚,那你的Ar…...
Nacos高可用集群部署实战:从架构设计到生产运维全解析
1. 项目概述:为什么Nacos集群部署是微服务架构的“定海神针”在微服务架构的实践中,服务注册与发现、配置管理是两大基石。Nacos作为Spring Cloud Alibaba生态的核心组件,集这两大功能于一身,其稳定性和可用性直接决定了整个微服务…...
C#面向对象封装详解:从字段到属性,为什么要用属性?
封装详解:从字段到属性1. 什么是封装封装是指隐藏类的内部实现细节,仅对外提供安全的访问接口,通过控制数据的读写操作来确保数据安全性。其核心目的是保护类中重要的内部数据。2. 字段直接暴露的问题当直接使用字段而不定义属性时࿰…...
Claude Code Ultraplan 远程多代理规划全解析:AI Agent、CCR远程容器、异步规划、状态机、计划传送与企业级自动化治理
一、先说结论:Ultraplan 到底解决了什么痛点?Ultraplan 可以理解为一种“远程规划模式”:用户在本地终端发起一个复杂任务,系统把规划阶段卸载到远程 CCR 容器中执行。本地终端不再被长时间占住,远程端可以使用更强模型…...
书匠策AI官网www.shujiangce.com|别再死磕“洗稿式降重“了!这才是2025论文通关的正确姿势
🫠 你有没有经历过这种"窒息时刻"? 凌晨两点,你对着查重报告,满屏飘红像开了大灯的KTV。你一句一句地改,把"因此"换成"所以",把"研究表明"换成"分析发现&qu…...
智慧能耗管理系统:嵌入式工控机在工业节能中的核心应用
1. 工厂能耗管理的痛点与智能化转型契机 在制造业摸爬滚打十几年,我见过太多工厂在能耗管理上的“粗放式”经营。电费单是每个月固定的大额支出,但具体电用在了哪里,哪个车间、哪条产线、甚至哪台设备是“电老虎”,很多时候都是一…...
终极指南:如何在5分钟内掌握SketchUp STL插件实现3D打印
终极指南:如何在5分钟内掌握SketchUp STL插件实现3D打印 【免费下载链接】sketchup-stl A SketchUp Ruby Extension that adds STL (STereoLithography) file format import and export. 项目地址: https://gitcode.com/gh_mirrors/sk/sketchup-stl SketchUp…...
挑战 100ms 延迟极限:深度拆解 dograh,构建企业级开源 WebRTC 实时语音智能体平台
发布日期: 2026-05-18标签: #VoiceAgent #WebRTC #语音智能体 #dograh #大模型 #实时音视频一、 引言在 2026 年,随着大模型多模态能力的爆发,传统的“打字输入、文字输出”交互模式正迅速向“纯语音实时对讲”演进。然而…...
