【Redis 开发】一人一单,超卖问题(悲观锁,乐观锁,分布式锁)

news2025/4/7 2:03:28

  • 悲观锁
  • 乐观锁
      • 第一种:版本号法
      • 第二种:CAS法
        • 实现乐观锁
      • 悲观锁与乐观锁的比较
  • 一人一单
  • 分布式锁
    • Redis实现分布式锁

悲观锁

认为线程问题一定会发生,因此在操作数据库之前先获取锁,确保线程串行执行,例如Synchronized,Lock都属于悲观锁

乐观锁

认为线程安全问题不一定会发生,因此不加锁,只有在更新数据的时候去判断有没有其他线程对数据做了修改

  1. 如果没有修改则认为是安全的,自己才更新数据
  2. 如果已经被其它线程修改说明发生了安全问题,此时可以重试或异常

乐观锁的关键是判断之前查询到的数据是否被修改过,有两种方法:

第一种:版本号法

就是在商品上添加版本号,一个线程查询用户的时候查询到id和版本号信息,当他需要进行修改数据的时候进行对比现在的版本号看有没有发生变化马,如果有就停止操作,并重新开始,如果没有则修改数据并将版本号加一,每个线程都执行此操作

第二种:CAS法

CAS法就是在版本号法上面做出的微调,将监控版本号修改为直接监控库存就行

实现乐观锁

就是在扣减库存的时候加上一个条件。判断库存有没有发生变化

boolean success = seckillVoucherService.update()
         .setSql("Stock=stock-1")
         .eq("voucher_id",voucherId).gt("stock",0)
         .update();

但是这样请求的失败率太高,我们可以进行稍微的修改,将判断条件库存大于0就行

悲观锁与乐观锁的比较

悲观锁:
优点:简单粗暴
缺点: 性能一般
乐观锁:
优点:性能好
缺点: 存在成功率低的问题

一人一单

超卖问题一般对于秒杀一个商品时所采用的技术,但是对于秒杀商品这种东西,一般一个用户只能够买一个,下一单

那么如何实现一人一单的问题呢:
就是在下单的时候,在订单数据库中进行查询如果该用户已经存在单子,那么会返回异常,如果在库中没有该用户,在创建新的订单,注意在创建新的订单之前需要使用悲观锁,防止多线程问题

注意:这里只能使用悲观锁,因为使用乐观锁无法进行判断

将从查询库中的信息开始到创建新的数据,封装在一个方法中,使用悲观锁synchronized并在该方法上添加事务

分布式锁

上述的乐观锁在进行用户并发中防止一个用户多次进行买单的处理,这只解决了单一服务器的多并发问题,当服务器处在集群中时,这个锁是锁不住的

原因:在多个集群中就会有多个jvm下的锁监视器,这些锁监视器只会监控本服务器下的悲观锁

所以为了控制集群下的多线程问题,我们采取分布式锁

那么什么是分布式锁:

就是多个服务器共用一个锁监视器,在同一个锁监视器中进行锁的监视

分布式锁的核心是实现多进程间的互斥,而满足这一点的方式有很多:
在这里插入图片描述

这里我们主要通过Redis实现分布式锁机制:

Redis实现分布式锁

实现和前面的讲的缓存击穿是所使用的方法类似
在Redis客户端模拟实现
set lock thread1 EX 10 NX
这样就会保证设置互斥和释放锁的原子性

多线程访问访问多集群的分布式锁工作流程:
在这里插入图片描述

  • 实现

首先定义一个锁的接口,实现该接口,利用Redis实现分布式锁功能

public interface ILock {

    /**
     * 尝试获取锁
     * @param timeoutSec
     * @return
     */
    boolean tryLock(long timeoutSec);

    /**
     * 释放锁
     */
    void unlock();
}

实现上述接口进行Redis操作

public class SimpleRedisLock implements ILock{

    private String name;
    private StringRedisTemplate stringRedisTemplate;

    public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {
        this.name = name;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    private static final String key_prefix="lock:";
    @Override
    public boolean tryLock(long timeoutSec) {
        //获取线程的标识
        long id = Thread.currentThread().getId();
        Boolean aBoolean = stringRedisTemplate.opsForValue().setIfAbsent(key_prefix + name, id + "", timeoutSec, TimeUnit.SECONDS);
        //自动拆箱的返回
        return Boolean.TRUE.equals(aBoolean);
    }

    @Override
    public void unlock() {
        //释放锁
        stringRedisTemplate.delete(key_prefix+name);
    }
}

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

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

相关文章

17 JavaScript 学习:正则表达式

JavaScript 正则表达式 JavaScript中正则表达式是一种强大的工具,用于在字符串中进行模式匹配和搜索。下面是一些JavaScript中使用正则表达式的基本知识: 创建正则表达式:可以使用字面量形式或者RegExp构造函数来创建正则表达式。 字面量形式…

【快速上手ESP32(基于ESP-IDFVSCode)】11-MQTT

MQTT MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)是一种基于发布/订阅模式的轻量级通讯协议,构建于TCP/IP协议之上。它最初由IBM在1999年发布,主要用于在硬件性能受限和网络状况不佳的情况下&…

M-LAG的基本概念

如图所示,用户侧设备Switch(可以是交换机或主机)通过M-LAG机制与另外两台设备(SwitchA和SwitchB)进行跨设备链路聚合,共同组成一个双活系统。这样可以实现SwitchA和SwitchB共同进行流量转发的功能&#xff…

泰迪智能科技助力中山三院放射科搭建生成式大模型应用

泰迪智能科技作为一家专业从事物联网、大数据及人工智能技术研发、咨询与培训的高科技企业,具有强大的技术研发实力和应用经验。中山大学附属第三医院放射科是集医疗、教学、科研工作于一体的广东省临床重点专科,具有深厚的医疗资源和科研基础。两者合作…

安卓和ios设置自己的短链

ios 的info.plist文件 设置 CFBundleURLSchemes 其中konnect 就是设置app的短链名称 <array><dict><key>CFBundleTypeRole</key><string>Editor</string><key>CFBundleURLName</key><string>org.konnect.app</str…

4.keepalive 与 Idle 监测

为什么需要 keepalive ? 假设你开了一个饭店,别人电话来订餐,电话通了后,订餐的说了一堆订餐要求,说着说 着,对方就不讲话了(可能忘记挂机/出去办事/线路故障等)。 这个时候你会一直握着电话等么? 不会 如果不会,那你一般怎么去做?会确认一句“你还在么?”,如果对…

常见的掼蛋误区

1、过于依赖大牌 很多新手玩家会觉得手中的大牌是必胜的保证&#xff0c;然而这种想法都是片面的。在掼蛋游戏中&#xff0c;一个合理的牌型组合往往比单一的大牌更有胜算。因此玩家要综合考虑的是手中的牌型和牌面大小。 2、盲目跟风 不少玩家在掼蛋中喜欢跟着对手的出牌思路走…

当NebulaGraph遇上智能体:图数据库智能助手

在数字化转型的浪潮中&#xff0c;图数据库技术凭借其出色的数据关联性能和灵活的查询功能&#xff0c;逐渐成为企业重要的技术选项。我们的团队之前曾经在两个项目中进行了图数据库的重构&#xff1a;一次是从OrientDB迁移到NebulaGraph&#xff0c;另一次是将ES系统迁移到Neb…

边写论文边发疯,多大仇啊?导师批注学生论文:建议把致谢部分烧掉

盼望着&#xff0c;盼望着&#xff0c;夏天来了&#xff0c;毕业的脚步近了。 于是乎&#xff0c;莘莘学子又开始幻想自己被导师带飞一路畅通顺利毕业了。 而且&#xff0c;如果可行的话&#xff0c;大家还希望能够这样&#xff1a; 然而&#xff0c;我阴暗的心中不由得泛起一…

只需几步,即可享有笔记小程序

本示例是一个简单的外卖查看店铺点菜的外卖微信小程序&#xff0c;小程序后端服务使用了MemFire Cloud&#xff0c;其中使用到的MemFire Cloud功能包括&#xff1a; 其中使用到的MemFire Cloud功能包括&#xff1a; 云数据库&#xff1a;存储外卖微信小程序所有数据表的信息。…

[Diffusion Model 笔记]DDIM 笔记 数学推导 Denoising Diffusion Implicit Models

目录 核心总结符号定义第一套&#xff0c;快速简单讲清采样方法继续分析&#xff0c;待定系数法求解图示理解关于参数sigma 本文是观看以下视频的笔记&#xff0c;强烈推荐观看最后的图示理解&#xff1a; https://www.bilibili.com/video/BV13P411J7dm/?spm_id_from333.788 论…

http基础了解

超文本传输协议&#xff08;HTTP&#xff09;是一个用于传输超媒体文档&#xff08;例如 HTML&#xff09;的应用层协议。它是为 Web 浏览器与 Web 服务器之间的通信而设计的&#xff0c;但也可以用于其他目的。HTTP 遵循经典的客户端—服务端模型&#xff0c;客户端打开一个连…

01、创建型-单例模式--只有一个实例

文章目录 前言一、基本介绍1.1 什么是单例模式1.2 为什么要用单例模式1.3 应用场景1.4 单例优缺点 二、单例模式的实现方式2.1 饿汉式单例2.1.1 静态变量方式2.1.2 静态代码块 2.2 懒汉式单例2.2.1 懒汉式单例2.2.2 懒汉式优化①-线程安全2.2.2 懒汉式优化②-双重检查锁2.2.3 懒…

力扣-1832.判断句子是否全为字母句

思路: 首先&#xff0c;我们初始化了一个长度为 26 的布尔值列表 exist&#xff0c;所有值都为 False&#xff0c;表示所有字母初始都未出现过。然后&#xff0c;我们遍历输入的字符串 sentence 中的每个字符。对于每个字符&#xff0c;我们通过计算其 ASCII 码值减去字母 a 的…

ArcGIS Pro专题地图系列教程

专题地图系列是ArcGIS Pro3.2的新功能。之前&#xff0c;如果要做8张相同区域的专题图&#xff0c;可能需要新建8个布局&#xff0c;分别进行排版&#xff0c;再导出。现在&#xff0c;一幅地图&#xff0c;一个布局&#xff0c;就可以完成这个流程。 原理是&#xff0c;根据单…

ROS python实现乌龟跟随

产生两只乌龟&#xff0c;中间的乌龟(A) 和 左下乌龟(B), B 会自动运行至A的位置&#xff0c;并且键盘控制时&#xff0c;只是控制 A 的运动&#xff0c;但是 B 可以跟随 A 运行 乌龟跟随实现的核心&#xff0c;是乌龟A和B都要发布相对世界坐标系的坐标信息&#xff0c;然后&am…

用例整体执行及pytest.ini文件

在我们写代码的过程中&#xff0c;一般都是右键或者命令行去执行一个用例 但是当我们写完后&#xff0c;需要整体执行一遍。那应该怎么搞呢&#xff1f; 我们可以在根目录下新建一个main.py或者run.py之类的文件&#xff0c;文件内容如下&#xff1a; if __name__ "__ma…

报错:图片验证码接口对接vue+springboot(下一个笔记会记录整个验证码的代码)

问题&#xff1a;空指针异常ai: 根据错误堆栈信息中提供的方法调用位置&#xff0c;看起来空指针异常是在 AuthCodeServiceImpl 类的 authUserCoded 方法的第 41 行发生的。 为了解决这个问题&#xff0c;你可以检查 AuthCodeServiceImpl 类中 authUserCoded 方法的第 41 行&am…

发那科FANUC机器人R-2000iB平衡缸维修攻略

在发那科机器人中&#xff0c;平衡缸扮演着稳定机械臂运动的关键角色。它通过内部的压力调节来平衡负载&#xff0c;保证机器人的精准定位和平稳操作。一旦出现法兰克机械手平衡缸故障或损坏&#xff0c;机器人的性能可能会大打折扣&#xff0c;因此及时且正确的FANUC机械手平衡…

2024通信会|迈向智慧配电网建设新时代,锐捷网络发布双平面配电通信解决方案

近期,以“加快推进通信数智化,助力构建新型能源体系”为主题的2024年能源网络通信创新应用大会在四川成都圆满结束,会议围绕构建新型能源体系和新型电力系统建设需求,探讨能源网络通信创新应用的最新趋势与成果、“主、配、微”通信网一体化融合、配电通信网、通信数智化转型等…