这么秀的操作我竟然到现在才了解到?合并请求~

简介: 在几年前,我就看到过有些博客写关于合并请求的文章,一开始我没有太在意,最近在看一个up讲述关于商品模块的牛X设计,为了提高高并发的处理能力,一般会用redis 自增自减来实现库存扣减,但是他采用合并扣减库存,也就是同一时间n个扣减库存会合并成一个请求,这样无疑减少了IO次数,也提高系统性能

前言


在几年前,我就看到过有些博客写关于合并请求的文章,一开始我没有太在意,最近在看一个up讲述关于商品模块的牛X设计,为了提高高并发的处理能力,一般会用redis 自增自减来实现库存扣减,但是他采用合并扣减库存,也就是同一时间n个扣减库存会合并成一个请求,这样无疑减少了IO次数,也提高系统性能。然后今天我看淘系有篇文章讲述 怎么提高自己的系统架构水平,里面也提到合并更新操作。

image.png

🐱那么这么秀的操作,真的不尝试下吗?Let's do it~

合并请求的目的


Why

A:你是否有遇到过类似场景,需要插入数据库很多很多条数据,那我们怎么优化?还有多个redis key请求的时候,如果我们每次都去拿到连接调用,可以发现时间会比较长,那怎么处理的?MQ场景,我们有一批的消息需要发送,是不是一个一个去投递?

答案是NO,我们会批量去处理这些任务,减少IO次数,其次批量处理可以减少往返网络通讯时间,提高效率。

通过简单demo感受下


秉着没吃过猪肉,也见过猪跑的想法,我们参照别人的思路:Future来实现异步调用,等到批量处理结果出来之后再返回。



show me your code


  1. 我们先想象下,需要什么变量,合并请求是随意合并吗? 答案当然不是,那么我们是将一段时间内的请求进行合并。

    那么需要一个标识来表示是否符合这段时间,或者算法。比如说一秒内,都是这个需要合并请求的范围。下面就用i来计数,需求:比如说超过2个并发,我们就需要合并请求了。

  2. 其次我们是不是要收集所有请求的对象,还有请求处理完,我们是不是要查询处理结果集,这样我们才好返回数据。所以加上LinkedList来缓存这一时刻的请求实体,以及使用set数据结构来模拟数据库db或者其他缓存处理结果的地方。


//某一时间段并发数量,可能1秒内
static int i = 0;

//这个一时刻的处理操作的队列
LinkedList<String> list = new LinkedList<>();

//可以代替DB,或者处理结果缓存地方
Set<String> set = new HashSet<>();
  1. 我们需要模拟一个业务处理器,定时执行list列表的任务,然后把结果丢到set结果集里头
CompletableFuture.runAsync(() -> {
    while (true) {
        if(!list.isEmpty()){
            Collections.shuffle(list);
            set.addAll(list);
            list.clear();
        }

    }
});
  1. 模拟并发合并请求操作
@GetMapping("firstRequest")
public boolean firstRequest() throws InterruptedException, ExecutionException, TimeoutException {
    //假设firstRequest,secondRequest同一个时间进来的
    i++;

    Thread.sleep(2000);
    if (i > 1) {
        list.add("firstRequest");
    }

    return CompletableFuture.supplyAsync(() -> {
        int i1 = 0;
        while (true) {
            i1++;
            if (i1 > 5) {
                return false;
            }
            if (set.remove("firstRequest")) {
                return true;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }).get();
}

@GetMapping("secondRequest")
public boolean secondRequest() throws ExecutionException, InterruptedException, TimeoutException {
    i++;
    if (i > 1) {
        list.add("secondRequest");
    }

    return CompletableFuture.supplyAsync(() -> {
        int i1 = 0;
        while (true) {
            i1++;
            if (i1 > 5) {
                return false;
            }
            if (set.remove("secondRequest")) {
                return true;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }).get();
}


🙋‍♂️ 我们看下第一个请求跟第二个请求,都做了啥操作?

首先第一个请求,会给i+1,代表当前时间段的计算器请求+1,然后等待一段时间,其实是为了,等第二个请求访问,让计算器达到并发等于2的场景。

然后分别将第一个跟第二个任务丢到list请求列表里头,然后我们异步任务去模拟业务处理,然后将处理结果丢到set结果返回集合中。请求通过future来定时请求返回结果,尝试5次,如果在这5次里头有结果,返回true。如果没有,则返回false。

到此我们代码实现完成了合并请求的逻辑。

合并请求的弊端


通过上面的例子,相信读者也看到有很多处等待重试拿数据的过程,比如说等待结果返回。

这个弊端都凸显出来了,如果数据量很大或者需要处理的任务很多的情况下,大家都在等待,那么服务器的资源一直被消耗,连接也会殆尽。

所以,我们需要有个合理的过期时间,比如说超过多少秒,请求的线程就不再等待直接返回超时,然后有补偿机制再次去查询处理结果。

相关文章
|
前端开发 Java Shell
Webstorm安装激活破解2022.09.07最新破解教程「永久激活,亲测有效」
本文讲的是2022.2.1版本的Webstorm破解、Webstorm激活码、Webstorm安装、Webstorm永久激活码的最新永久激活教程,本文有mac和windows系统的idea安装教程。
9157 0
Webstorm安装激活破解2022.09.07最新破解教程「永久激活,亲测有效」
|
10月前
|
运维 监控 安全
区块链应用上云实践
本文介绍基于阿里云BaaS平台的区块链应用上云全流程实践,涵盖联盟链搭建、智能合约开发、应用集成、监控运维与安全管控,并以供应链金融场景为例,详解多组织协同、数据上链、权限管理及可视化运维的落地步骤,助力企业高效构建安全可控的区块链应用,推动业务数字化转型。(239字)
557 0
|
8月前
|
人工智能 监控 安全
AI 软件的开发上线
2026年AI软件上线已远超技术发布,是涵盖算法备案、安全评估、标识义务、端云协同部署、灰度测试、LLMOps监控及RLHF 2.0自学习迭代的系统工程,合规与治理成本成为关键门槛。(239字)
|
存储 人工智能 运维
为什么新兴行业更需要 NaaS? 2025-09-08 14:40:38
在数字化浪潮下,AI、短剧、电商、数字文娱等新兴行业迅速崛起,业务追求敏捷高效,但网络却常成瓶颈。传统网络部署慢、成本高、体验差,难以满足其快速发展需求。NaaS(网络即服务)应运而生,提供分钟级部署、弹性带宽、合规加速与专业运维支持,助力企业专注创新,真正实现“敢快跑”。
|
Java Linux iOS开发
如何配置 Java 环境变量:设置 JAVA_HOME 和 PATH
本文详细介绍如何在Windows和Linux/macOS系统上配置Java环境变量。
22655 12
|
人工智能 自然语言处理 安全
详解:poe ai官网是什么_poe ai官方网站_Poe AI官网入口
在全球范围内,人工智能的迅速发展引发了广泛关注,而Poe AI作为一款前沿的AI聊天平台,正处于这场技术变革的前沿
2810 10
gitlab--trigger 触发不同项目之间的 CI、 触发同一项目下的其他 ci
gitlab--trigger 触发不同项目之间的 CI、 触发同一项目下的其他 ci
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
存储 监控 Linux
在Linux中,如何使用LVM管理逻辑卷?
在Linux中,如何使用LVM管理逻辑卷?
|
数据采集 Web App开发 JavaScript
如何在Puppeteer中实现表单自动填写与提交:问卷调查
本文介绍了如何使用 Puppeteer 和代理 IP 技术实现在线问卷调查的自动填写与提交。Puppeteer 是一个基于 Node.js 的无头浏览器自动化库,能够模拟用户行为,填写表单并提交数据。通过配置代理 IP,可以提高匿名性和爬取效率,避免因频繁请求而被封禁。本文提供了详细的代码示例和技术分析,帮助读者理解和应用这一技术。
595 0