【干货】看看我司消息队列用啥,全网最接地气pulsar教程(含业务解耦demo源码)

news2024/11/15 10:23:47

前言

🍊缘由

消息队列一出手,pulsar就知有没有

在这里插入图片描述

🐣闪亮主角

大家好,我是JavaDog程序狗

今天跟大家分享pulsar,一个分布式的消息发布/订阅传递平台。

本狗以身入局,将pulsar的使用场景,结合实际使用案例,进行大白话分析

通过简单代码demo进行讲解,pulsar在java中如何使用?如何通过pulsar进行异步解耦?…等

在这里插入图片描述

😈你想听的故事

狗哥最近在整理学习笔记时,偶然在百度发现pulsar相关的教程竟然大部分付费会员才能看,淦!

在这里插入图片描述

首先,我不反对知识付费,但是花钱才能看总感觉差那么一点意思。

于是乎,狗哥将我司日常使用的消息队列pulsar进行总结整理,让大家一次性免费学个够,不付费也能学的酣畅淋漓

🎁如何获取源码

公众号:【JavaDog程序狗】

关注公众号,发送 “pulsar”,无任何套路即可获得!

在这里插入图片描述

正文

🎯主要目标

1.pulsar是什么
2.pulsar有什么核心特性
3.pulsar与其他消息队列区别
4.docker如何安装pulsar
5.docker如何安装pulsar-manager
6.实际电商业务分析
7.java中如何使用pulsar解决业务问题

🍪目标讲解

一.pulsar是什么?
1.官网地址

https://pulsar.apache.org/

在这里插入图片描述

2.pulsar简介

Apache Pulsar 是一个高性能、可扩展且灵活的分布式消息传递和流处理平台

👽人话解释

Pulsar 就是一个消息中间件,和Kafka、RocketMQ功能差不多,多用于削峰解耦

3.pulsar发展历程
  • Pulsar 最初由 Yahoo 开发,并在内部大规模使用。

  • 2016 年,Yahoo 将 Pulsar 开源,并将其捐赠给 Apache 软件基金会。

  • 2018 年,Pulsar 成为了 Apache 软件基金会的顶级项目

在这里插入图片描述


二.pulsar核心特性?
1.消息传递
  • 支持多种消息订阅模式
    如独占(Exclusive)、灾备(Failover)、共享(Shared)和 Key_Shared 订阅。

  • 支持消息的延迟发送,
    即消息可以在发布后的一段时间内被消费者消费。

2.存储与计算分离架构
  • Pulsar 采用了存储与计算分离的设计,这意味着消息的处理逻辑(Broker)与数据存储可以独立扩展。
  • 这种架构使得 Pulsar 在扩展性和可靠性方面表现优异。
3.多租户支持
  • Pulsar 支持多租户环境,允许不同的应用程序或团队在同一个集群中运行而互不影响。
4.持久化存储
  • Pulsar 提供了持久化的消息存储能力,确保即使在故障发生时消息也不会丢失。
5.轻量级函数式计算
  • Pulsar 支持在消息传递之上构建简单的函数式计算,这使得它不仅仅是一个消息队列,还可以用于实现流处理应用。
6.跨地域复制
  • Pulsar 允许跨多个地理位置的数据中心进行数据复制,以实现高可用性和灾难恢复。

👽人话解释

Pulsar 就像是一个快递中转站,但它不仅能高效地处理大量的包裹(消息),还能确保每个包裹都能准确无误地送达目的地(消费者)


三.pulsar与其他消息队列区别?
PulsarActiveMQRabbitMQRocketMQKafka
单机吞吐量十万级万级万级十万级十万级
开发语言JavaJavaErlangJavaJava/Scala
维护者ApacheApacheSpringApacheApache
社区活跃度
消费模式独占、共享、灾备、key共享P2P、Pub-Subdirect、topic、Headers、fanout基于Topic和MessageTag基于Topic的Pub-Sub
顺序消息支持不支持不支持支持支持
稳定性一般一般较差
集群支持集群模式主备模式复制模式主备模式集群可扩展性强

关于消息队列的选取,在实际案例中取决于你的具体需求和技术背景

  1. 大规模数据流处理
    推荐使用:Apache Pulsar 或 Apache Kafka
    理由:
    Pulsar:支持存储与计算分离,可以独立扩展存储和处理能力,非常适合大规模数据流处理。
    Kafka:以其高性能和低延迟著称,适合处理大量实时数据流。

  2. 多租户环境
    推荐使用:Apache Pulsar
    理由:
    Pulsar:提供了强大的多租户支持,可以为不同的应用程序和服务分配独立的命名空间和资源。

  3. 高可用性和容错性
    推荐使用:Apache Pulsar 或 Apache Kafka
    理由:
    Pulsar:具有内置的高可用性支持,消息持久化到磁盘,支持消息复制。
    Kafka:同样具有高可用性,支持消息持久化和副本机制。

  4. 灵活的消息路由
    推荐使用:Apache RabbitMQ
    理由:
    RabbitMQ:基于 AMQP 协议,支持复杂的路由规则和消息模式,非常适合需要灵活消息路由的场景。

  5. 简单易用性
    推荐使用:Apache RabbitMQ 或 RocketMQ
    理由:
    RabbitMQ:提供了丰富的客户端库,易于集成。
    RocketMQ:API 设计简洁,易于理解和使用。


四.docker如何安装pulsar

小伙伴如果不会在windows上安装docker,请查看狗哥之前文章

【从零开始】Docker Desktop:听说你小子要玩我

https://mp.weixin.qq.com/s/kZXSpU8Cc2yswEglozAvTQ

1.安装pulsar

拉取pulsar2.9.2版本镜像

在Windows PowerShell,输入拉取pulsar镜像命令

docker pull apachepulsar/pulsar:2.9.2

在这里插入图片描述

2.启动pulsar

启动pulsar2.9.2单机版

docker run -it -p 6650:6650 -p 8080:8080 apachepulsar/pulsar:2.9.2 bin/pulsar standalone

在这里插入图片描述

3.关闭对话框

使用Ctrl+P+Q组合键。当你在容器内部时,按下这个组合键可以将当前的终端会话断开,同时保持容器继续运行。

Ctrl+P+Q

在这里插入图片描述

五.docker如何安装pulsar-manager

什么是pulsar-manager?

Pulsar Manager 是 Apache Pulsar 的一个管理工具,它提供了一个用户界面和 RESTful API 用于管理和监控 Pulsar 集群
Pulsar Manager 可以帮助管理员执行一系列集群管理任务,例如创建和删除命名空间、管理 topic、查看集群状态等。

👽人话解释

pulsar-manager就是一个pulsar的可视化工具,功能就像Navicat差不多

1.安装pulsar-manager

拉取pulsar-manager0.2.0版本镜像

在Windows PowerShell,输入拉取pulsar镜像命令

docker pull apachepulsar/pulsar-manager:v0.2.0

在这里插入图片描述

2.启动pulsar-manager

启动pulsar-manager v0.2.0

docker run -it -p 9527:9527 -p 7750:7750 -e SPRING_CONFIGURATION_FILE=/pulsar-manager/pulsar-manager/application.properties apachepulsar/pulsar-manager:v0.2.0

在这里插入图片描述

3.关闭对话框

使用Ctrl+P+Q组合键。当你在容器内部时,按下这个组合键可以将当前的终端会话断开,同时保持容器继续运行。

Ctrl+P+Q

在这里插入图片描述

4.设置账号和密码

设置账号为admin,密码为apachepulsar

CSRF_TOKEN=$(curl http://localhost:7750/pulsar-manager/csrf-token)
curl \
   -H 'X-XSRF-TOKEN: $CSRF_TOKEN' \
   -H 'Cookie: XSRF-TOKEN=$CSRF_TOKEN;' \
   -H "Content-Type: application/json" \
   -X PUT http://localhost:7750/pulsar-manager/users/superuser \
   -d '{"name": "admin", "password": "apachepulsar", "description": "test", "email": "xxx@test.org"}'

在这里插入图片描述

5.登录控制台验证

访问 http://localhost:9527/

输入账号:admin 密码:apachepulsar

在这里插入图片描述

6.新增环境

新增环境,填写环境名,及启动的pulsar单体应用地址

在这里插入图片描述

7.查看控制台

在这里插入图片描述

  • Clusters (集群)
    定义: Pulsar 集群是一组运行 Pulsar Broker 的服务器集合。
    作用: 多个集群可以被配置来实现地理分布式的部署,以支持数据复制和灾难恢复
    管理: 使用 pulsar-admin clusters 命令来管理集群。

  • Tenants (租户)
    定义: 租户代表了组织或应用程序的逻辑分隔。
    作用: 租户用于隔离不同组织的数据,并且可以为每个租户设置访问控制策略
    管理: 使用 pulsar-admin tenants 命令来管理租户。

  • Namespaces (命名空间)
    定义: 命名空间是在租户内部进一步划分资源的方式。
    作用: 命名空间用于隔离不同应用程序的数据,并且可以为每个命名空间设置不同的策略和配置
    管理: 使用 pulsar-admin namespaces 命令来管理命名空间。

  • Topics (主题)
    定义: 主题是消息的实际载体,是生产者发送消息和消费者接收消息的地方。
    作用: 每个主题都属于一个特定的命名空间,主题可以有多个消费者订阅
    管理: 使用 pulsar-admin topics 命令来管理主题。

  • Tokens (令牌)
    定义: 令牌是一种认证机制,允许客户端通过提供一个安全令牌来访问 Pulsar 资源。
    作用: 令牌通常用于简化客户端认证过程,特别是对于不需要长期凭证的情况
    管理: 使用 pulsar-admin tokens 命令来管理令牌。


六.实际电商业务分析

🌰场景实例

张三在电商平台买了一个产品,支付成功后,张三等着收货就好…

但是在程序业务视角来看,支付成功后,其实还有很多下游服务在默默执行。

如库存、物流、订单服务都会有相应逻辑执行。

我们就模拟真实电商案例,来讲解下如何使用pulsar以及pulsar能解决什么痛点问题

在这里插入图片描述

情况一:没有使用pulsar消息队列,业务正常串行执行

张三支付成功后,更新订单,更新库存,更新物流…串行操作,每个服务都耗时2秒

在这里插入图片描述

这种串行的执行方式有很大的问题,如果整个链路串行执行,那么响应的时间就是每个业务执行时间想加,更新订单(2秒),更新库存(2秒),更新物流(2秒),总共耗时6秒

如果还有其他下游业务,链路时间会一直叠加,造成张三用户访问等待时长,并且如果链路中有失败,则会导致整个链路异常

情况二:使用pulsar消息队列,实现异步解耦

张三支付成功后,更新订单,更新库存,更新物流…并行操作

在这里插入图片描述

这种使用异步解耦方式,每个服务都异步执行,响应立刻返回,用户体验绝佳


七.java中如何使用pulsar解决业务问题

我们将上面六中的两种情况进行代码实操,串行执行和使用pulsar异步解耦

1.代码结构

在这里插入图片描述

2.关键代码
  • 引入pulsar依赖

在这里插入图片描述

  <dependency>
      <groupId>org.apache.pulsar</groupId>
      <artifactId>pulsar-client</artifactId>
      <version>${pulsar.version}</version>
  </dependency>
  • pulsar配置

在这里插入图片描述

pulsar:
  #支付topic
  pay-topic: persistent://public/default/pay-topic
  #支付subscription
  pay-subscription: pay-subscription
  #订单topic
  order-topic: persistent://public/default/order-topic
  #订单subscription
  order-subscription: order-subscription
  #库存topic
  stock-topic: persistent://public/default/stock-topic
  #库存subscription
  stock-subscription: stock-subscription
  #物流topic
  logistics-topic: persistent://public/default/logistics-topic
  #物流subscription
  logistics-subscription: logistics-subscription

在这里插入图片描述

# Pulsar配置
pulsar:
  url: pulsar://192.168.31.27:6650
  • pulsar生产者

在这里插入图片描述

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

package net.javadog.pulsar.pay.service.pulsar.impl;

import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import net.javadog.pulsar.logistics.service.pulsar.LogisticsPulsarProducer;
import net.javadog.pulsar.order.service.pulsar.OrderPulsarProducer;
import net.javadog.pulsar.stock.service.pulsar.StockPulsarProducer;
import org.apache.pulsar.client.api.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.net.InetAddress;
import java.util.concurrent.TimeUnit;

/**
 * 支付异步通知-消费者
 *
 * @author hdx
 * @version 1.0
 * @since 2024.07
 */
@Slf4j
@Component
public class PayPulsarConsumer {

    @Value("${pulsar.url}")
    private String url;
    @Value("${pulsar.pay-topic}")
    private String topic;
    @Value("${pulsar.pay-subscription}")
    private String subscription;

    private PulsarClient client = null;
    private Consumer<byte[]> consumer = null;

    private OrderPulsarProducer orderPulsarProducer;

    private StockPulsarProducer stockPulsarProducer;

    private LogisticsPulsarProducer logisticsPulsarProducer;


    @Resource
    public void setStockPulsarProducer(StockPulsarProducer stockPulsarProducer) {
        this.stockPulsarProducer = stockPulsarProducer;
    }

    @Resource
    public void setOrderPulsarProducer(OrderPulsarProducer orderPulsarProducer) {
        this.orderPulsarProducer = orderPulsarProducer;
    }

    @Resource
    public void setLogisticsPulsarProducer(LogisticsPulsarProducer logisticsPulsarProducer) {
        this.logisticsPulsarProducer = logisticsPulsarProducer;
    }

    /**
     * 使用@PostConstruct注解用于在依赖关系注入完成之后需要执行的方法上,以执行任何初始化
     */
    @PostConstruct
    public void initPulsar() throws Exception {
        try {
            //构造Pulsar client
            client = PulsarClient.builder()
                    .serviceUrl(url)
                    .build();
            final String ip = InetAddress.getLocalHost().getHostAddress().replaceAll("\\.", "");
            //创建consumer
            consumer = client.newConsumer()
                    .topic(topic.split(","))
                    .consumerName("payPulsarConsumer" + ip)
                    .subscriptionName(subscription)
                    //指定消费模式,包含:Exclusive,Failover,Shared,Key_Shared。默认Exclusive模式
                    .subscriptionType(SubscriptionType.Shared)
                    //指定从哪里开始消费还有Latest,valueof可选,默认Latest
                    .subscriptionInitialPosition(SubscriptionInitialPosition.Latest)
                    //指定消费失败后延迟多久broker重新发送消息给consumer,默认60s
                    .negativeAckRedeliveryDelay(60, TimeUnit.SECONDS)
                    .batchReceivePolicy(BatchReceivePolicy.builder()
                    .maxNumBytes(10*1024*1024)
                    .maxNumMessages(-1)
                    .timeout(100, TimeUnit.MILLISECONDS)
                    .build())
                    .subscribe();
        } catch (Exception e) {
            log.error("Pulsar初始化异常:", e);
            throw e;
        }
    }

    public void start() throws Exception {
        //消费消息
        log.debug("支付消费者启动");
        while (true) {
            Message<byte[]> message = consumer.receive();
            log.debug("消费消息中,message:{}", message);
            final String id = new String(message.getValue());

            if (ObjectUtil.isNotNull(id)) {
                try {
                    messageHandle(id);
                    consumer.acknowledge(message);
                } catch (Exception e) {
                    log.error("消费Pulsar支付数据异常,key【{}】,orderId【{}】:", message.getKey(), id, e);
                }
            }

        }
    }

    private void messageHandle(String orderId) {
        log.info("【支付消费】,orderId:{}", orderId);

        // 订单生产消息
        orderPulsarProducer.handler(orderId, 0);

        // 库存生产消息
        stockPulsarProducer.handler(orderId, 0);

        // 物流生产消息
        logisticsPulsarProducer.handler(orderId, 0);
    }

    public void close() {
        try {
            consumer.close();
        } catch (PulsarClientException e) {
            log.error("关闭Pulsar消费者失败:", e);
        }
        try {
            client.close();
        } catch (PulsarClientException e) {
            log.error("关闭Pulsar连接失败:", e);
        }
    }

}

3.启动调试
  • 程序启动

在pulsar-boot-main下找到Application并运行。注意:pulsar一定先起来!!

在这里插入图片描述

  • 打开swagger接口文档

在控制台打开打印的swagger地址,进行接口调试

在这里插入图片描述

  • 访问串行调用方法A

随意录入orderId,点击支付-普通串行支付-方式A接口【Execute】按钮,查看结果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 访问消息队列解耦方法B

随意录入orderId,点击采用消息队列解耦-方式B接口【Execute】按钮,查看结果

在这里插入图片描述

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

4.演示总结

demo代码逻辑简单,业务逻辑清晰,以最直观的响应时间来展示使用pulsar异步解耦优势,并使用优雅的分层使代码结构干净整洁

希望大家能够下载demo实操一下,好记性不如烂笔头;彻底掌握使用pulsar的小技巧,将其运用到实战中,真正体现它的优点。

🍈猜你想问

如何与狗哥联系进行探讨
关注公众号【JavaDog程序狗】

公众号回复【入群】或者【加入】,便可成为【程序员学习交流摸鱼群】的一员,问题随便问,牛逼随便吹,目前群内已有超过300+个小伙伴啦!!!

2.踩踩狗哥博客

javadog.net

里面有狗哥的私密联系方式呦 😘

大家可以在里面留言,随意发挥,有问必答

在这里插入图片描述

🍯猜你喜欢

文章推荐

【实操】Spring Cloud Alibaba AI,阿里AI这不得玩一下(含前后端源码)

【规范】看看人家Git提交描述,那叫一个规矩

【项目实战】SpringBoot+uniapp+uview2打造H5+小程序+APP入门学习的聊天小项目

【项目实战】SpringBoot+uniapp+uview2打造一个企业黑红名单吐槽小程序

【模块分层】还不会SpringBoot项目模块分层?来这手把手教你!

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

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

相关文章

【flask框架搭建服务器demo】Python 使用轻量级 Flask 框架搭建 Web 服务器可视化数据库数据demo

本文适合刚入门flask框架用来熟悉项目的开发人员&#xff0c;关于flask框架的组成概念一些用法请参考下面的文章 https://blog.csdn.net/qq_47452807/article/details/122289200 本文主要给出一个可视化sqlite数据库数据的demo&#xff0c;先展示一下效果&#xff1a; 主要的…

前端速通面经八股系列(二)—— HTML篇

HTML高频面经八股目录 1. src和href的区别2. 对HTML语义化的理解3. DOCTYPE(⽂档类型) 的作⽤4. script标签中defer和async的区别5. 常⽤的meta标签有哪些6. HTML5有哪些更新1. 语义化标签2. 媒体标签3. 表单4. 进度条、度量器5.DOM查询操作6. Web存储7. 其他 7. img的srcset属…

Python 图像处理进阶:特征提取与图像分类

特征提取 特征提取是计算机视觉中的一个重要环节&#xff0c;它可以从图像中提取出有助于后续处理的特征&#xff0c;比如用于识别和分类的关键点、纹理等。常见的特征提取方法包括SIFT、SURF和ORB等。 SIFT&#xff08;尺度不变特征变换&#xff09; SIFT是一种用于检测图像…

Web-ssrfme--redis 未授权访问攻击

目录 1、题目源码 2、测试ssrf 3、发现主机 4、发现服务 5、redis 未授权访问攻击 6&#xff0c;拿flag 1、题目源码 <?php highlight_file(__file__); function curl($url){ $ch curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_HEADER…

用Maven开发Spring Boot 项目

一、初识 Spring Boot Spring Boot框架是一 套开源的后台开发框架&#xff0c; 继承了Spring MVC框架的前辈SSM框架的优秀特性&#xff0c;通过注解大幅减少程序员写配置的工作量。从企业开发角度来看&#xff0c;它提供了自动化配置&#xff0c;内嵌容器和兼容Maven等核心功…

银河麒麟桌面操作系统V10:如何快速将应用固定到任务栏?

银河麒麟桌面操作系统V10&#xff1a;如何快速将应用固定到任务栏&#xff1f; 1、图形界面方法2、命令行方法2.1 固定应用2.2 取消固定 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在银河麒麟V10中&#xff0c;/usr/share/applications…

Vue 绘制圆形 上下左右

效果图 代码&#xff1a; <div style"transform: rotate(45deg)"><div id"top"><div id"top-left" click"addformData(true, form.lat, 0.000003, lat)"><ArrowUpBold style"height: 25px; width: 25px; tr…

winform 实现优美的进度条 包含百分比

winform 原生控件中包含进度条控件 ProgressBar。 但这个控件并没有告诉我们如何在上面实现 显示百分比进度的方式&#xff0c;或者说根本就不支持。但没 有百分比显示的进度条是没有灵魂的&#xff0c;可能是有点让人一头雾水的。 还好我们可以通过实现 ProgressBar 的 OnP…

海康VisionMaster使用学习笔记18-常见问题排查

常见问题排查思路 常见问题排查方法-安装阶段 常见问题排查方法-启动阶段 常见问题排查方法-使用阶段 常见问题排查方法-相关资料

outlook在“对我发送的邮件应用规则”时只能移动邮件副本的问题和解决方案

outlook在“对我发送的邮件应用规则时”只能移动邮件副本的问题 问题描述问题的解决方案第一步第二步 其他说明参考 问题描述 如果我们想对自己发送的邮件进行分类&#xff0c;可以使用规则将已发送的邮件移动到指定文件夹中&#xff0c;但是。当操作对象为“自己发送的邮件时…

运维学习————LVS集群和Keepalived+LVS高可用

目录 官网&#xff1a;LVS中文官网 一、概念 二、组成及软件工作层次图 ​编辑 三、整体架构 四、名词解释 五、三种工作模式 1、LVS-NAT 2、LVS-TUN 3、LVS-DR 六、DR模式的实现 1、克隆出LVS&#xff0c;配置虚拟IP 2、配置Nginx的虚拟IP Nginx1的配置 Nginx2…

Linux的一些实例

# 1.编写脚本&#xff0c;让用户输入firstname和lastname&#xff0c;最后在屏幕上显示your full name is&#xff1a; #!/bin/bash read -p "please input firstname:" var1 read -p "please input lastname:" var2 echo "your full name is:$var1…

【机器学习】线性回归的概念以及如何从最小二乘法推导到正规方程和实际线性回归实例(含python代码)

引言 线性回归是一种广泛应用于统计分析、经济预测、机器学习等领域的建模方法。它旨在通过自变量&#xff08;解释变量&#xff09;来预测因变量&#xff08;响应变量&#xff09;的值 文章目录 引言一、线性回归的概念1.1 线性回归的基本概念1.2 最小二乘法1.2.1 最小二乘法的…

来了!!!来了!!!--我需要在Docker中运行Java应用程序,但是没有Docker经验,你能给我一个简单的入门指南吗?

在Docker中运行Java应用程序的简单入门指南&#xff1a; 1.安装Docker 首先&#xff0c;确保你的系统上安装了Docker。你可以从Docker官网下载并安装适合你操作系统的Docker版本。 Windows10 安装 Docker&#xff0c;每个步骤作者亲测&#xff0c;细节记录最全教程 2. 编写D…

Sublime Text 配置 Terminal (CMD)

1. 安装package 按住 【ctrlshiftp】 , 在弹出的输入框中输入“install”&#xff0c;选择“install package”,回车,等待20秒左右 2. 安装terminal 按住 【ctrlshiftp】 , 在弹出的输入框中输入“install”&#xff0c;选择“install package”,回车,等待新弹窗出来&#…

稀土长余辉发光剂在陶瓷中的应用

稀土长余辉发光剂是一种特殊的发光材料&#xff0c;主要由稀土元素&#xff08;如镧、铈、钕、铽、镝等&#xff09;掺杂而成&#xff0c;基于电子陷阱机理&#xff0c;可实现长余辉效果&#xff0c;发光时间长达6-8小时。 稀土长余辉发光材料在陶瓷上的应用主要利用了其在激…

不相交的线(Lc1035)——动态规划

在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。 现在&#xff0c;可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线&#xff0c;这些直线需要同时满足&#xff1a; nums1[i] nums2[j]且绘制的直线不与任何其他连线&#xff08;非水平线&#xff09;相…

论文翻译:ChatGPT passing USMLE shines a spotlight on the flaws of medical education

ChatGPT passing USMLE shines a spotlight on the flaws of medical education https://journals.plos.org/digitalhealth/article?id10.1371/journal.pdig.0000205 ChatGPT 通过美国执业医师执照考试&#xff08;USMLE&#xff09;凸显了医学教育的缺陷 阿马拉奇B姆巴克韦1…

你不知道的100个国外搜索引擎升级版

首先是要支持国产品牌磁力狐&#xff0d;cilih.com DMOZ – 一个多语种、开放式网站目录。 Food Blog Search -可以让你从上千个博客和网站查找菜谱。 Swoogle – 一个语义、文件、术语和数据的搜索引擎&#xff0c;不同于普通的搜索引擎。 SimilarSiteSearch – 帮你找到相似…

排序------快速排序(C语言实现)

目录 快速排序算法 例题 题目描述 具体代码&#xff1a; 代码分析 函数定义&#xff1a; 主函数&#xff1a; 快速排序算法 快速排序&#xff08;QuickSort&#xff09;是一种高效的排序算法&#xff0c;它采用分治策略&#xff0c;通过选择一个“基准”元素并将其他元素…