秒杀系统的业务流程以及优化方案(实现异步秒杀)

这篇具有很好参考价值的文章主要介绍了秒杀系统的业务流程以及优化方案(实现异步秒杀)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

先看基本的业务流程

秒杀系统的业务流程以及优化方案(实现异步秒杀),redis,分布式项目调优,junit,redis,性能优化

 那么我们可以看到整个流程都是一个线程来完成的,这样的话耗时还是很长的,那么可不可以采用多线程去实现呢?

首先我们要思考怎么对业务进行拆分,可以想象一个我们去饭店点餐,会有前台接待,询问订单,之后将小票传给后厨去做饭,这样就会快很多,也可以接待更多的客人

也就是说 一个线程负责去读数据库做准备工作,另一个线程去实现写操作,如下图中所示:

秒杀系统的业务流程以及优化方案(实现异步秒杀),redis,分布式项目调优,junit,redis,性能优化

    确定了我们可以将判断库存和检验一人一单业务抽取出来之后,我们在想一下 还能不能优化,这个时候我们会发现,这两个操作还是在数据库进行的,那么mysql的并发本身也是不高的,现在我们就要通过另一个性能更好的数据库进行实现,就是redis

秒杀系统的业务流程以及优化方案(实现异步秒杀),redis,分布式项目调优,junit,redis,性能优化     

 这样只需要业务进行到校验完成就可以给用户返回下单完成的信息,之后在通过另一个线程异步进行扣减库存操作

redis中实现上面两个操作的业务流程如下:

秒杀系统的业务流程以及优化方案(实现异步秒杀),redis,分布式项目调优,junit,redis,性能优化

 由于操作流程较长,应该使用lua脚本来保证原子性

将上面的逻辑采用lua脚本进行编写,之后程序运行首先判断返回值如果是0就说明用户有下单资格,如果是1或者2就说明用户没有资格下单

如果有下单资格就可以将用户id,优惠券id,和订单id存入一个阻塞队列里面,之后异步进行写入数据库操作

整体流程:

秒杀系统的业务流程以及优化方案(实现异步秒杀),redis,分布式项目调优,junit,redis,性能优化

提供lua脚本代码

-- 1.参数列表
-- 1.1.优惠券id
local voucherId = ARGV[1]
-- 1.2.用户id
local userId = ARGV[2]
-- 1.3.订单id
local orderId = ARGV[3]

-- 2.数据key
-- 2.1.库存key
local stockKey = 'seckill:stock:' .. voucherId
-- 2.2.订单key
local orderKey = 'seckill:order:' .. voucherId

-- 3.脚本业务
-- 3.1.判断库存是否充足 get stockKey
if(tonumber(redis.call('get', stockKey)) <= 0) then
    -- 3.2.库存不足,返回1
    return 1
end
-- 3.2.判断用户是否下单 SISMEMBER orderKey userId
if(redis.call('sismember', orderKey, userId) == 1) then
    -- 3.3.存在,说明是重复下单,返回2
    return 2
end
-- 3.4.扣库存 incrby stockKey -1
redis.call('incrby', stockKey, -1)
-- 3.5.下单(保存用户)sadd orderKey userId
redis.call('sadd', orderKey, userId)
-- 3.6.发送消息到队列中, XADD stream.orders * k1 v1 k2 v2 ...
redis.call('xadd', 'stream.orders', '*', 'userId', userId, 'voucherId', voucherId, 'id', orderId)
return 0

使用方式

    private static final DefaultRedisScript<Long> SECKILL_SCRIPT;

    static {
        SECKILL_SCRIPT = new DefaultRedisScript<>();
        SECKILL_SCRIPT.setLocation(new ClassPathResource("seckill.lua"));
        SECKILL_SCRIPT.setResultType(Long.class);
    }
  @Override
    public Result seckillVoucher(Long voucherId) {
        Long userId = UserHolder.getUser().getId();
        long orderId = redisIdWorker.nextId("order");
        // 1.执行lua脚本
        Long result = stringRedisTemplate.execute(
                SECKILL_SCRIPT,
                Collections.emptyList(),
                voucherId.toString(), userId.toString(), String.valueOf(orderId)
        );
        int r = result.intValue();
        // 2.判断结果是否为0
        if (r != 0) {
            // 2.1.不为0 ,代表没有购买资格
            return Result.fail(r == 1 ? "库存不足" : "不能重复下单");
        }
        // 3.返回订单id
        return Result.ok(orderId);
    }

 redis的流程到此就完结了,接下来就是使用阻塞队列存储要进行写操作的信息

阻塞队列的实现方式通常是使用一个先进先出的队列来存储元素,同时使用锁来实现线程安全。当队列为空时,put()方法会被阻塞,直到有元素被添加到队列中;当队列满时,put()方法同样会被阻塞,直到队列中有元素被移除。

阻塞队列通常用于生产者-消费者模型中,生产者将元素添加到队列中,消费者从队列中取出元素进行处理。通过使用阻塞队列,可以避免生产者和消费者之间的直接交互,从而简化了代码的设计和维护。

首先我们可以可以使用java自带的阻塞队列实现,提供一个样例:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class ProducerConsumerExample {
    public static void main(String[] args) {
        BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10); // 创建一个容量为10的阻塞队列

        Thread producer = new Thread(new Producer(queue));
        Thread consumer = new Thread(new Consumer(queue));

        producer.start();
        consumer.start();
    }
}

class Producer implements Runnable {
    private BlockingQueue<Integer> queue;

    public Producer(BlockingQueue<Integer> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            try {
                System.out.println("Producing " + i);
                queue.put(i); // 将元素添加到队列中
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Consumer implements Runnable {
    private BlockingQueue<Integer> queue;

    public Consumer(BlockingQueue<Integer> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        while (true) {
            try {
                Integer item = queue.take(); // 从队列中取出元素进行处理
                System.out.println("Consuming " + item);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

当然如果想要性能更好的话,我们可以采用消息队列来做文章来源地址https://www.toymoban.com/news/detail-672797.html

到了这里,关于秒杀系统的业务流程以及优化方案(实现异步秒杀)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 企业内业务系统与Activiti流程引擎的结合(一)

    Activiti流程接口中台 此模块分以下几部分: 一、数据库表设计 二、后台接口设计 系统使用的Activiti版本  一、初始化的数据库表 1. Activiti 涉及25张表 ACT_EVT_LOG                        事件日志 ACT_GE_BYTEARRAY            部署流程的资源(bpmn、图片) ACT_GE_PROPERTY           

    2023年04月12日
    浏览(36)
  • 企业内业务系统与Activiti流程引擎的结合(五)

    书接上回 Activiti流程接口中台 接口实现 查询指定人员办理过的任务 /task/user/{userNo}/hiProcinst 查询 activiti 相关表 请求参数 返回参数

    2024年02月13日
    浏览(42)
  • 基于若依的ruoyi-nbcio流程管理系统自定义业务撤回功能的修复

    更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码: https://gitee.com/nbacheng/nbcio-boot 前端代码:https://gitee.com/nbacheng/nbcio-vue.git 在线演示(包括H

    2024年01月18日
    浏览(51)
  • 基于若依的ruoyi-nbcio流程管理系统修复自定义业务表单的收回功能

    更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码: https://gitee.com/nbacheng/nbcio-boot 前端代码:https://gitee.com/nbacheng/nbcio-vue.git 在线演示(包括H

    2024年01月18日
    浏览(50)
  • 使用Golang实现一套流程可配置,适用于广告、推荐系统的业务性框架——简单应用

    在诸如广告、推荐等系统中,我们往往会涉及过滤、召回和排序等过程。随着系统业务变得复杂,代码的耦合和交错会让项目跌入难以维护的深渊。于是模块化设计是复杂系统的必备基础。这篇文章介绍的业务框架脱胎于线上多人协作开发、高并发的竞价广告系统,在实践中

    2024年02月14日
    浏览(44)
  • 业务流程测试

    主要问题存在于 : 1、测试点分析:逻辑性不强 2、测试用例:关于,要细致到什么程度,不太明确 3、测试用例设计时是依据需求说明书还是系统? 流程规范的公司,一定是基于需求说明书(或原型图)来设计测试用例 进入项目的时间节点来看 项目初期介入,依据 需求 说

    2023年04月11日
    浏览(39)
  • 安全策略与业务需求不匹配:安全规则与业务流程的优先级不一致

    随着网络攻击手段层出不穷、黑客技术的日益升级和网络安全法规的日益严格化,企业在保障信息安全的同时也面临着越来越大的压力和挑战。其中一个突出的问题是**安全策略与业务需求的不匹配问题**。这主要表现为安全规则的制定与企业日常的业务流程存在很大的差异和

    2024年01月21日
    浏览(44)
  • AI智能语音机器人的基本业务流程

    先画个图,了解下AI语音机器人的基本业务流程。 上图是一个AI语音机器人的业务流程,简单来说就是首先要配置话术,就是告诉机器人在遇到问题该怎么回答,这个不同公司不同行业的差别比较大,所以一般每个客户都会配置其个性化的话术。 话术配置完成后,需要给账号

    2024年02月12日
    浏览(58)
  • 业务流程自动化:ThinkAutomation Professional Crack

    ThinkAutomation 助力您的业务流程自动化。自动执行本地和基于云的业务流程,以降低成本并节省时间。 自动化传入的通信渠道,监控数据库,对传入的Webhook,Web表单和聊天机器人做出反应。处理文档、附件、本地文件和其他邮件源。 从传入消息中解析和提取数据并执行业务流

    2024年02月09日
    浏览(39)
  • 尚上优选社区团购业务流程及微服务技术实现

    尚上优选是一家社区电商项目,采用“当日下单+次日送达+门店自提”的模式,围绕社区居民日常生活所需,满足不同用户的差异化需求,通过完善的 仓储配送体系,以便捷的方式和舒心的服务提升了每一个普通家庭的消费体验。 掌握社区团购业务流程及实现方式 掌握Spri

    2024年02月10日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包