分布式秒杀方案--java

news2024/9/20 9:33:03

前提:先把商品详情和秒杀商品缓存redis中,减少对数据库的访问(可使用定时任务)
秒杀商品无非就是那几步(前面还可能会有一些判断,如用户是否登录,一人一单,秒杀时间验证等)
1一人一单
2.判断库存
3.减库存
4.创建订单

秒杀需要解决的问题?

1.解决超卖问题

1.1这样秒杀肯定会出现超卖的情况,所以必须加锁。加锁无非就两种锁,乐观锁和悲观锁。
悲观锁:直接在1前上锁即可,这里使用redisson里的可重入锁

        // 获取分布式锁对象
        RLock lock = redissonClient.getLock("seckillLock");
        try {
            //等待5秒获取锁,执行60秒还是没有释放锁就强制释放
            boolean b = lock.tryLock(5L, 60L, TimeUnit.SECONDS);
            if (b){
               SeckillProductVo  seckillProductVo = seckillProductService.find(time, seckillId);
                //1.保证库存足够
                if (seckillProductVo.getStockCount()<=0){
                    return Result.error(SeckillCodeMsg.SECKILL_STOCK_OVER);
                }
              //下面两个方法必须写在一起避免事务未提交,未扣减库存就释放锁
            //2.扣减库存
            //3.生成订单
                orderInfo=orderInfoService.doSeckill(phone,seckillProductVo);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

1.2乐观锁:这个就不需要用代码演示了
1一人一单
2.判断库存
3.减库存
4.创建订单

在3.减库存的时候mysql语句 and 库存>0即可,MySQL会有自己的行锁。所以每次只会执行一次修改操作。以上两个方法都不会造成超卖
但是却未能解决秒杀问题,原因高并发请求都进入了数据库来查库,会造成数据库崩溃或阻塞其它mysql的执行。

2.重复下单问题,如何解决?

2.1 在4.创建订单后,把用户的唯一标识,id或phone存入redis的set中 key->{phone1,phone2}
redisTemplate.opsForSet().isMember(orderKey,phone)返回true或false
流程变成 1.一人一单 2.判断库存 3.减库存 4.创建订单 5.redisTemplate.opsForSet().add(orderKey,phone);

2.2 但是这样并不能完全解决重复下单,比如用户同时点了两次请求。极端条件下,a线程进入步骤1的判断,从1到4 需要进行很多操作,当a线程未走到5时,b线程就进来了这样也会造成重复下单。所以必须使用数据库的唯一索引进行解决,把用户唯一标识和秒杀商品唯一标识做成唯一索引即可解决
在这里插入图片描述
也就是在 4.创建订单 的时候会出现报错,3库存减掉之后数据回滚即可。
然而redis里的库存却和数据库的就不一样了,redis是无法被回滚的。后面会使用cannal对数据库和redis的库存进行同步。。。
有些人可能会说了,2.1没有解决重复问题,为什么不直接用2.2解决?2.1在大部分情况下都能解决,避免有人多次点击秒杀对数据造成压力,所以2.1和2.2一起使用才是最佳的选择

3.流量控制
3.1 必须把请求拦截在数据库之外,如果库存只有10个,也只有10个线程能最终到达数据库就是一个比较理想的方案
所以把数据库的秒杀商品库存存入redis中,进行预售,只有redis里能执行-1操作才能进入service,这样就极大的减少了请求到service层中

3.2 如果同一个秒杀时间段有多个商品 如100个秒杀商品,每个秒杀商品的库存为10个,那么就会有10*100个请求到达数据库,如果是淘宝的双11显然秒杀的商品会更多。那么我们就需要进行流量的削峰控制。
在这里插入图片描述
从controller中拦截消息,service取消息的时候慢慢拿,mq能够占时的让一部分请求存储在里面排队处理,service根据自己的处理能力去拿。有些人可能会说排队处理不是很慢?在controller中发完消息这个请求已经可以算是结束了,用户不会立即看到抢购结果。后面经过
在这里插入图片描述

在这里插入图片描述
最终方案
在这里插入图片描述

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

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

相关文章

springboot web 增加不存在的url返回200状态码 vue 打包设置

spring boot项目增加 html web页面访问 1. 首先 application.properties 文件中增加配置&#xff0c;指定静态资源目录&#xff08;包括html的存放&#xff09; spring.resources.static-locationsclasspath:/webapp/,classpath:/webapp/static/ 2. 项目目录 3. 如果有实现 …

适用于基于晶圆键合的3D集成应用的高效单晶圆清洗

引言 不同的微电子工艺需要非常干净的表面以防止颗粒污染。其中&#xff0c;晶圆直接键合对颗粒清洁度的要求非常严格。直接晶圆键合包括通过简单地将两种材料的光滑且干净的表面接触来将两种材料连接在一起&#xff08;图1&#xff09;。在室温和压力下&#xff0c;两种材料表…

休闲零食新的机会在哪里?

世间唯一不变的&#xff0c;或许只有变化本身。 来自同花顺iFinD的数据显示&#xff0c;上半年A股21家休闲食品概念股累计实现营收350.45亿元&#xff0c;净利润26.46亿元。其中&#xff0c;良品铺子的营业收入排在首位&#xff0c;为39.87亿元&#xff0c;桃李面包的净利润排…

Node.js 文件夹遍历方法:探索优化代码的秘诀

在 Node.js 开发中&#xff0c;经常需要对文件系统进行操作&#xff0c;包括遍历文件夹以获取文件列表。本文将讨论使用 Node.js 遍历文件夹的几种常用方法&#xff0c;并通过一个实际案例来演示如何实现。 基本概念 在开始之前&#xff0c;让我们了解一些基本的概念&#xff…

自动化测试:Selenium中的时间等待

在 Selenium 中&#xff0c;时间等待指在测试用例中等待某个操作完成或某个事件发生的时间。Selenium 中提供了多种方式来进行时间等待&#xff0c;包括使用 ExpectedConditions 中的 presence_of_element_located 和 visibility_of_element_located 方法等待元素可见或不可见&…

数据孤岛的突破口在哪里?

国务院于2021年12月发布的《“十四五”数字经济发展规划》中提到&#xff0c;我国数字经济发展中数字鸿沟问题未得到有效解决&#xff0c;各行业应充分发挥数据要素作用&#xff0c;加强数据治理和监管工作。“数据孤岛”问题虽早已被提出&#xff0c;但至今仍然存在&#xff0…

【Git】Git 基础

Git 基础 参考 Git 中文文档 — https://git-scm.com/book/zh/v2 1.介绍 Git 是目前世界上最先进的分布式版本控制系统&#xff0c;有这么几个特点&#xff1a; 分布式&#xff1a;是用来保存工程源代码历史状态的命令行工具保存点&#xff1a;保存点可以追溯源码中的文件…

【docker快速部署微服务若依管理系统(RuoYi-Cloud)】

工作原因&#xff0c;需要一个比较完整的开源项目测试本公司产品。偶然发现RuoYi-Cloud非常适合&#xff0c;它有足够多的中间件&#xff0c;而且官方提供docker安装&#xff0c;但我本人在安装过程中遇到了很多坑&#xff0c;在这里记录一下防止下次会再次遇到。 项目地址 ht…

OpenCV 01(图像加载与显示)

一、机器视觉 现在说的机器视觉(Machine Vision)一般指计算机视觉(Computer Vision), 简单来说就是研究如何使机器看懂东西。就是是指用摄影机和电脑代替人眼对目标进行识别、跟踪和测量等机器视觉&#xff0c;并进一步做图形处理&#xff0c;使电脑处理成为更适合人眼观察或传…

关于elementui表单验证数字的问题

千里之行始于足下 熟能生巧&#xff0c;不熟怎么生巧 最近编写项目时候遇到一个这样的问题&#xff0c;elementui 表单验证价格是否为数字&#xff0c; 正常来说只需要将规则写为如下 { required: true, type: number, message: "请填写正确的数字", trigger: "…

引爆用户参与:消息重弹,让您的推送不再被忽略

在当前各大APP拉新促活成本居高不下的大背景下&#xff0c;如何稳定存量用户、提升用户粘性就显得尤为关键。从促销活动到个性化推荐&#xff0c;从互动通知到功能提醒&#xff0c;消息推送已成为各大APP连接存量用户和目标市场之间的桥梁&#xff0c;通过点击推送&#xff0c;…

ADS1219芯片解读

使用10-kΩ热敏电阻的温度测量是使用比率测量实现的实现最佳精度的方法。模拟电源电压AVDD用作电阻器分压器配置中的热敏电阻&#xff0c;以及ADS1219的外部参考电压V REF。 ADS1219的输出代码和热敏电阻R热敏电阻之间的关系是通过以下方程式。公式 10将输入AIN0处的输入电压表…

全网超50万粉丝的Linux大咖良许,出书了!

全网超50万粉丝的Linux大咖良许 出书了&#xff01; 今天我们要说的就是这本由Linux领域头部号主&#xff0c;良许老师编写的这本《速学Linux&#xff1a;系统应用从入门到精通》 如果你是刚开始学习Linux的小白同学&#xff0c;相信你已经体会到与学习一门编程语言相比&…

【源码解读】VUE2.0和VUE3.0响应式区别?

数据劫持的目的 VUE2.0和VUE3.0实现响应式的底层逻辑&#xff0c;是对数据做劫持&#xff0c;为什么要劫持数据呢&#xff1f;是因为&#xff0c;劫持数据后才可以&#xff0c;在更改数据同时对页面进行重新渲染&#xff0c;从而达到响应式。 VUE3.0响应原理 VUE3.0使用了ES…

适配器模式:如何让不兼容的接口变得兼容

在软件开发中&#xff0c;我们经常会遇到这样的情况&#xff1a;我们需要使用一个现有的类或者接口&#xff0c;但它与我们系统的目标接口不兼容&#xff0c;而我们又不能修改它。这时候&#xff0c;我们该怎么办呢&#xff1f;大多数情况下我们都可以使用适配器模式来解决这个…

hutool的HttpRequest.post的使用-包括上传文档等多个传参【总结版本】

首先hutool已经为我们封装好了远程调用的接口&#xff0c;我们只要将对应的传参和方式对应填写即可 hutool官方文档 1实际应用 post 常见的使用json传参&#xff0c;contend type为application/json RequestMapping("login") ResponseBody public static String s…

中国人大与加拿大女王大学中外合作办学金融硕士——学习是你世界的圆吗

有人说&#xff0c;可以把每个人的世界比作一个圆&#xff0c;学习是半径&#xff0c;半径越大&#xff0c;拥有的世界就越广阔。你认同这种观点吗&#xff0c;金融领域的你有想过拓宽知识的边界吗&#xff1f;来人大女王中外合作办学金融硕士项目在职读研&#xff0c;超越自我…

【多线程】线程 与 进程

线程 与 进程 一. 进程1. 操作系统2. 什么是进程/任务&#xff08;Process/Task&#xff09;3. 为什么要有进程3. 操作系统怎样管理进程4. 进程控制块抽象(PCB Process Control Block)5. 进程调度6. 内存分配 —— 内存管理&#xff08;Memory Manage&#xff09;7. 进程间通信…

【C++】匿名对象 | explicit | static静态成员 | 友元

匿名对象 有些情况下&#xff0c;我们创建变量只是临时用一用&#xff0c;以后不会再用到了。这时&#xff0c;如果创建变量还要起名字&#xff0c;是不是很多余&#xff1f; 对此&#xff0c;C引入了 匿名对象 供临时使用。 例如&#xff1a;如果我们创建对象slt&#xff0c…

什么是主动元数据管理?有何优势?

元数据是描述数据的数据&#xff0c;它提供数据的来源、含义、位置、所有权和创建等信息&#xff0c;主要用于跟踪、分类和分析。 元数据管理则是对元数据的创建、存储、整合、控制的一整套流程&#xff0c;是数据治理过程的一部分&#xff0c;能够支持基于元数据的相关需求和…