分布式解决方案与实战

news2024/11/11 21:25:09

分布式多线程性能调优

使用多线程优化接口

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

	//下单业务
    public Object order( long userId){
        long start = System.currentTimeMillis();//方法的开始时间戳(ms)

        JSONObject orderInfo = remoteService.createOrder(userId);

        Callable<JSONObject> callable1 = new Callable<JSONObject>() {
            @Override
            public JSONObject call() throws Exception {
                JSONObject goodsInfo = remoteService.dealGoods(orderInfo);
                return goodsInfo;
            }
        };
        Callable<JSONObject> callable2 = new Callable<JSONObject>() {
            @Override
            public JSONObject call() throws Exception {
                JSONObject pointsInfo = remoteService.dealPoints(orderInfo);
                return pointsInfo;
            }
        };
        Callable<JSONObject> callable3 = new Callable<JSONObject>() {
            @Override
            public JSONObject call() throws Exception {

                JSONObject deliverInfo = remoteService.dealDeliver(orderInfo);
                return deliverInfo;
            }
        };
        LeeFutureTask<JSONObject> task1 = new LeeFutureTask(callable1);
        LeeFutureTask<JSONObject> task2 = new LeeFutureTask(callable2);
        LeeFutureTask<JSONObject> task3 = new LeeFutureTask(callable3);

        Thread thread1 =new Thread(task1);
        Thread thread2 =new Thread(task2);
        Thread thread3 =new Thread(task3);

        thread1.start();
        thread2.start();
        thread3.start();

        try {
            orderInfo.putAll(task1.get());
            orderInfo.putAll(task2.get());
            orderInfo.putAll(task3.get());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }

        long end = System.currentTimeMillis();//方法的开始时间戳(ms)
        System.out.println(end-start);//打印这个方法的执行时间
        return orderInfo;
    }

后台批处理的优化

在这里插入图片描述

public JSONObject orderFastbatch (long userId) throws Exception{

        JSONObject orderInfo = remoteService.createOrderFast(userId);

        //JSONObject goodsInfo = remoteService.dealGoodsFast(orderInfo); //这里是单个的请求,想做成批量+异步的方式
        //orderInfo.putAll(goodsInfo);
        CompletableFuture<JSONObject> future = new CompletableFuture<>();
        Request request = new Request();
        request.future =future;
        request.object = orderInfo;
        queue.add(request);
        return future.get(); //这里类似于FutureTask  的get方法,去异步的方式拿结果
    }

    //定义一个JUC中的MQ
    LinkedBlockingQueue<Request> queue = new LinkedBlockingQueue();
    class Request{
        JSONObject object;
        CompletableFuture<JSONObject> future;
    }

    @PostConstruct
    public void DoBiz(){
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
        executorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                int size =queue.size();
                if(size ==0) return;//没有数据在queue中,定时任务不需要执行什么

                if(size >1000) size=1000;//这里限制每次批量封装的最多是1000

                List<JSONObject> ListJSONRepuest = new ArrayList<>();
                List<Request>  ListRequest = new ArrayList<>();
                for( int i =0 ;i <size;i++){
                    Request request =queue.poll();//从MQ中拉取
                    ListRequest.add(request);
                    ListJSONRepuest.add(request.object);
                }
                //调用了多少次批量接口
                List<JSONObject> ListJSONReponse  = remoteService.dealGoodsFastBatch(ListJSONRepuest);
                System.out.println("调用批量接口,本地组装的数据:"+size+"条");
                for(JSONObject  JSONReponse:ListJSONReponse){//这里可以使用hashmap 的方式减少一轮遍历。
                    for(Request  request:ListRequest){
                        String  request_OrderId =request.object.get("orderId").toString();
                        String  response_OrderId =JSONReponse.get("orderId").toString();
                       if(request_OrderId.equals(response_OrderId)){
                           request.future.complete(JSONReponse);
                       }
                    }
                }
            }
        }, 3000, 50, TimeUnit.MILLISECONDS);

    }
//处理库存信息 (批量接口)  1000,
    public List<JSONObject> dealGoodsFastBatch( List<JSONObject> objectList) {
        List<JSONObject> list = objectList;
        Iterator it = list.iterator();
        while(it.hasNext()){
            JSONObject result =(JSONObject)it.next();
            result.put("dealGoods", "ok");
        }
        return  list;
    }

批处理与MySQL的综合性优化

如果做了批量处理的话。
1W个请求,高并发请求,其实里面针对的修改库存会集中在一些热点数据8000个在一个商品。
应用层基于批量的接口进行优化。
伪代码:
for循环遍历list,把所有相同的goods_id放到hashmap进行扣减计数即可。

分布式锁

单机锁:sync、lock
MySQL去实现分布式锁–for update (行锁)

Redis

分布式锁的第一种常见方案:Redis来实现分布式锁。Redis key-value键值对的数据库–内存。

Redis的分布式锁的实现逻辑:
1、加锁,setnx key value
1)为了避免死锁问题setnx完之后设置TTL失效时间
2)为了TTL的失效的时候业务还未完成导致的多个应用抢到锁的BUG,这里可以使用一个守护线程,来不断的去续锁(延长key的TTL)

2、解锁del key
无论是加锁,还是解锁,这里涉及到多个命令。要解决原子性问题:
1、复合命令实现加锁。set lock 9527 ex 10 nx
2、解锁的逻辑中:在del之前一定要判断:只有持有锁的应用或线程,才能去解锁成功,否则都是失败。value做文章。存一个唯一标识。

if (get ==应用的保存的值)del
else释放锁失败

使用Lua脚本

锁的可重入。A抢到了锁,没有释放锁之前,依然可以lock进入加锁逻辑的。

Zookeeper

在这里插入图片描述
1、连接ZK、创建分布式锁的根节点/lock
2、一个线程获取锁时,create ()在/lock西面创建1个临时顺序节点3、使用getChildren()获取当前所有字节点,并且对子节点进行排序
4、判断当前创建的节点是否是所有子节点中最小的节点,如果是,则获取锁->执行对应的业务逻辑->在结束的时候使用delete()方法删除该节点。
否则需要等待其他的节点的释放锁、
5、当一个线程需要释放锁的,删除该节点,其他的线程获取当前节点前的一个节点来获取锁。

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

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

相关文章

如何看待「前端已死论」?

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

Xcode编写基于C++的动态连接库(dylib)且用node-ffi-napi测试

创建一个dylib工程示例 在 Xcode 中创建一个动态链接库&#xff08;.dylib 文件&#xff09;的步骤如下&#xff1a; 打开 Xcode&#xff1a; 打开 Xcode 应用程序。 创建新的工程&#xff1a; 选择 "Create a new Xcode project"&#xff0c;或者使用菜单 File &g…

STM32 PVD掉电检测功能的使用方法

STM32 PVD掉电检测功能的使用方法 前言 在实际应用场景中&#xff0c;可能会出现设备电源电压异常下降或掉电的情况&#xff0c;因此&#xff0c;有时候需要检测设备是否掉电&#xff0c;或者在设备掉电的瞬间做一些紧急关机处理&#xff0c;比如保存重要的用户数据&#xff…

Java基础语法之多态

什么是多态 通俗来说就是多种形态&#xff0c;具体点就i是去完成某个行为&#xff0c;当不同的对象去完成时会产生不同的状态 都是吃东西&#xff0c;狗是吃狗粮&#xff0c;猫是吃猫粮 向上转型 本质就是创建一个子类对象&#xff0c;将其当作父类对象来使用 语法格式&am…

[Kubernetes]2. k8s集群中部署基于nodejs golang的项目以及Pod、Deployment详解

一. 创建k8s部署的镜像 1.部署nodejs项目 (1).上传nodejs项目到节点node1 (2).压缩nodejs项目 (3).构建nodejsDockerfile 1).创建nodejsDockerfile 具体可参考:[Docker]十.Docker Swarm讲解,在/root下创建nodejsDockerfile,具体代码如下: FROM node #把压缩文件COPY到镜像的…

pycharm多线程报错的问题(未解决)

暂未解决&#xff01;若有佬知道如何解决&#xff0c;还请不吝赐教~~~先谢过啦 问题描述&#xff1a; 看了一下可能是这里的问题&#xff1a; 根据建议&#xff0c;在walks之前加了 freeze_support() 但是没有效果。 关键是&#xff0c;在jupyter上运行是没有问题的&#x…

逆向获取某音乐软件的加密(js逆向)

本文仅用于技术交流&#xff0c;不得以危害或者是侵犯他人利益为目的使用文中介绍的代码模块&#xff0c;若有侵权请联系作者更改。 老套路&#xff0c;打开开发者工具&#xff0c;直接开始找到需要的数据位置&#xff0c;然后观察参数&#xff0c;请求头&#xff0c;cookie是…

1- Electron 创建项目、初始化项目

Electron官网 Build cross-platform desktop apps with JavaScript, HTML, and CSS | Electron Electron 初始化 初始化项目 - 构造package.json npm init -y 安装Electron模块包 npm i electron -D // 注意&#xff01;如果报错查看node包是否太高 配置启动脚本 {&quo…

安全护航:迅软DSE加密软件在设计院所图纸文件中的成功案例分享

近年来&#xff0c;随着信息化强国战略和可持续发展方针的推动&#xff0c;国内各大设计院所和建筑机构积极推进信息化建设&#xff0c;将电子文件作为主要的信息存储方式&#xff0c;并将其作为单位内外部信息交换的关键载体。在这一背景下&#xff0c;创新设计作为建筑设计单…

如何实现自己的训练集

在anaconda prompt中查看&#xff08;conda info -e&#xff09;、删除&#xff08;conda remove -n aimbot_env&#xff09;虚拟环境 其中aimbot_env是虚拟环境的名字 是否要删掉&#xff1f;选y 创建虚拟环境&#xff08;conda create -n aimbot_env python3.7.4&#xff0…

微信小程序---自定义组件

目录 1.局部引用组件 2.全局引用组件 3.组件和页面的区别 4.自定义组件样式 5.properties属性 6.data和properties的区别 7.数据监听器 8.纯数据字段 9.自定义组件-组件的生命周期 lifetimes节点 10.组件所在的页面的生命周期 pageLifetimes节点 11.插槽 &#x…

Redis设计与实现之简单的动态

目录 一、内部数据结构 二、简单动态字符串 1、sds的用途 实现字符串对象 将sds代替C默认的char*类型 2、Redis中的字符串 sds的实现 3、优化追加操作 4、sds 模块的 API 三、Redis动态字符串的内存分配和释放是如何进行的&#xff1f; 四、Redis动态字符串的扩容策略…

css+js 选项卡动画效果

选项卡上下左右翻转动画效果 <template><div class"web-box"><div class"topTitle"><div class"topTitle1">标题标题</div></div><div class"info-wrap"><div style"width: 100%;h…

互联网加竞赛 python 机器视觉 车牌识别 - opencv 深度学习 机器学习

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于python 机器视觉 的车牌识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;3分 &#x1f9ff; 更多资…

掌握iText:轻松处理PDF文档-高级篇-添加页眉和页脚

推荐语 本文介绍了如何使用iText编程库为PDF文档添加自定义的页眉和页脚。通过指定位置、大小、字体和颜色等属性&#xff0c;你可以将文本、图像或其他元素添加到每一页的固定位置&#xff0c;实现专业、可读的自定义页眉和页脚效果。这对于需要批量处理大量PDF文档或需要更精…

基于轻量级GhostNet模型开发构建工业生产制造场景下滚珠丝杠传动表面缺陷图像识别系统

轻量级识别模型在我们前面的博文中已经有过很多实践了&#xff0c;感兴趣的话可以自行移步阅读&#xff1a; 《移动端轻量级模型开发谁更胜一筹&#xff0c;efficientnet、mobilenetv2、mobilenetv3、ghostnet、mnasnet、shufflenetv2驾驶危险行为识别模型对比开发测试》 《基…

YOLOv5改进 | 2023卷积篇 | AKConv轻量级架构下的高效检测(既轻量又提点)

一、本文介绍 本文给大家带来的改进内容是AKConv是一种创新的变核卷积&#xff0c;它旨在解决标准卷积操作中的固有缺陷&#xff08;采样形状是固定的&#xff09;&#xff0c;AKConv的核心思想在于它为卷积核提供了任意数量的参数和任意采样形状&#xff0c;能够使用任意数量…

***Cpolar配置外网访问和Dashy

Dashy是一个开源的自托管的导航页配置服务,具有易于使用的可视化编辑器、状态检查、小工具和主题等功能。你可以将自己常用的一些网站聚合起来放在一起,形成自己的导航页。一款功能超强大,颜值爆表的可定制专属导航页工具 结合cpolar内网工具,我们实现无需部署到公网服务器…

Spring Boot 3 整合 WebSocket (STOMP协议) 和 Vue 3 实现实时通信

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

基于 Webpack5 Module Federation 的业务解耦实践

前言 本文中会提到很多目前数栈中使用的特定名词&#xff0c;统一做下解释描述 dt-common&#xff1a;每个子产品都会引入的公共包(类似 NPM 包) AppMenus&#xff1a;在子产品中快速进入到其他子产品的导航栏&#xff0c;统一维护在 dt-common 中&#xff0c;子产品从 dt-com…