RDMA 高性能架构基本原理与设计方案

news2024/11/13 9:33:00

 在进行本文的学习学习之前,我们先对RDMA是什么做一个简单的科普与认识:一文带你了解什么是RDMA-CSDN博客

目录:

目录:

一、RDMA和传统网络方案的比较 

1.1 传统网络方案:

1.1.1 缺点一:以太网卡(socket)通信过程

1.1.2 缺点二:以太网卡(socket)数据流

1.2 RDMA的方案

1.2.1 优点:RDMA的控制通路和数据通路

1.2.2 优点:RDMA 网卡的数据流 

二、RDMA协议类型

三、RDMA软件架构:

 四、RDMA 的基本元素和操作类型

4.1 WQ&WQE

4.1.1 工作队列元素(WQE)

4.1.2 工作队列(WQ)

4.1.3 关系与比较

4.2 QP(核心元素)

4.2.1 队列对(QP)

4.2.2 发送队列(SQ)

4.2.3 接收队列(RQ)

4.2.4 SEND-RECV流程

4.2.5 图示说明

4.2.6 队列对(QP)

4.2.7 QP编号(QPN)

4.2.8 通信流程

4.3 CQ

4.3.1 完成队列(CQ)

4.3.2 完成队列元素(CQE)

​编辑

4.3.3 一般流程

4.4 RDMA Write操作(典型操作)

4.4.1 RDMA WRITE操作

4.4.2 地址转换

4.4.3 实际应用和性能优势

 4.5 Memory Region

4.5.1 Memory Region(MR)

4.5.2 解决问题

4.5.3 实际应用

4.6 RDMA各种元素的实体形式

五、RDMA 设计思路 

5.1 应用程序的执行流程和每一步的主要工作

​编辑

 5.2 设计思路

5.2.1 初始化和配置等低频操作可以进入内核态执行

5.2.2 数据传输等高频操作旁路内核

5.2.3 独立的QP、CQ资源保证多线程并发

5.2.4 小结


RDMA的主要优点包括低延迟、高吞吐量、减少CPU负担和支持零拷贝网络。它允许数据直接在网络接口卡(NIC)和内存之间传输,减少了数据传输过程中的中间环节,从而显著降低了延迟。RDMA技术能够实现高速的数据传输,适用于需要大量数据交换的应用场景。由于数据传输不需要CPU的参与,CPU可以更多地专注于计算任务,提高了系统的整体效率。RDMA的软件架构通常包括用户空间库、内核驱动和硬件设备三个主要部分。典型的应用场景包括高性能计算、数据中心网络和存储系统等RDMA的基本元素包括队列对、保护域和内存区域等,这些元素共同完成了RDMA通信的建立和数据传输。设计RDMA的主要思路是尽可能减少数据传输路径上的中间环节,降低延迟,提高吞吐量,并减轻CPU的负担。

一、RDMA和传统网络方案的比较 

1.1 传统网络方案:

1.1.1 缺点一:以太网卡(socket)通信过程

下图展示了使用传统以太网卡时,两台机器通讯过程中所需要的软件模块(分层)以及软硬件之间的关系。

传统的sendsendto等系统调用涉及了从用户态到内核态的转换,这一过程会增加数据传输的延迟。当应用程序使用这些系统调用发送数据时,数据首先会被复制到内核空间的缓冲区,然后才从内核发送到网络上。这种数据在用户空间和内核空间之间的复制操作,以及与之相关的上下文切换,是导致额外开销和延迟的主要原因。

1.1.2 缺点二:以太网卡(socket)数据流

下图展示了使用以太网卡(Socket模型)时,数据在两个运行在不同机器上的APP之间传导的过程。假设机器1为发送方,机器2为接收方。

传统网络数据传输过程中数据在用户空间、内核空间和硬件之间的流动过程:

  1. 用户空间至内核空间的数据复制:应用层通过系统调用(如sendsendto)将数据从用户空间传输到内核空间。这一步骤涉及CPU将数据复制到内核缓冲区中。

  2. 网络协议处理:一旦数据到达内核空间,内核中的网络协议栈会给数据添加必要的网络协议头(例如TCP/IP头),可能还会进行数据的分片和封装处理,并进行必要的校验。

  3. DMA传输到网卡使用DMA(Direct Memory Access)技术,数据从主机内存被高效地复制到发送端网卡的内部缓存中,准备发送到网络上。

  4. 通过物理链路发送数据发送端网卡处理完数据后,通过物理链路(例如以太网)将数据发送给对端设备的网卡。

  5. 接收端硬件DMA操作:接收端的网卡通过DMA操作将接收到的数据从网卡的缓存复制到系统内存中,这避免了CPU直接参与数据的初步传输过程。

  6. 数据处理与传递给用户空间:CPU介入处理接收到的数据包,如进行逐层的解析和校验等,最后将数据从内核空间复制到用户空间的应用程序中。

1. 用户空间与内核空间之间的数据复制:在传统的网络通信中,当应用程序需要发送数据时,它必须通过系统调用(如`send`或`sendto`)将数据从用户空间复制到内核空间。这个复制过程增加了数据传输的延迟,因为它需要CPU的直接参与。同样,在接收数据时,数据需要从内核空间复制到用户空间,这同样增加了延迟。

2. CPU参与数据包的封装和解析:在发送数据时,CPU需要参与数据包的封装过程,包括添加各种网络协议头(如IP、TCP/UDP头)。在接收数据时,CPU需要对数据包进行解析和校验,以确保数据的完整性和正确性。这些操作在数据量较大时会对CPU造成较重的负担,因为CPU需要处理大量的数据包,这会占用大量的CPU资源,影响系统的整体性能

1.2 RDMA的方案

1.2.1 优点:RDMA的控制通路和数据通路

下图中有一左一右两台机器,可互相发送接收数据。在这里将RDMA的分层模型分成“控制通路"和“数据通路控制通路需要进入内核态准备通信所需的各种资源(如QP、MR等),数据通路负责数据收发(如RDMA Write:和RDMA Read)。

RDMA技术允许网络设备直接访问主机内存,而不需要CPU的介入。这使得数据可以在网络设备和内存之间直接传输,大大减少了延迟和CPU的负担。

1.2.2 优点:RDMA 网卡的数据流 

下图展示了使用RDMA网卡时,数据在两个运行在不同机器上的APP之间传递的过程。假设机器1为发送方,机器2为接收方。

  1. 发送端网卡的数据处理

    • 数据首先从用户空间通过系统调用(如sendsendto)复制到内核空间。
    • 内核中的网络协议栈负责添加各协议层头部(如IP、TCP/UDP头)和校验信息。
    • 然后,数据通过DMA(Direct Memory Access)技术从内核空间的缓冲区复制到发送端网卡的内部缓存中。
    • 发送端网卡通过物理链路将数据发送给对端的网卡。
  2. 接收端网卡的数据处理

    • 接收端网卡通过物理链路接收到数据后,首先进行初步处理,如校验和检查。
    • 如果校验通过,网卡会使用DMA技术将数据从网卡的内部缓存复制到内核空间的缓冲区。
    • 内核中的网络协议栈负责剥离各协议层头部和校验信息,并将数据传递给相应的套接字缓冲区(socket buffer)。
    • 最后,数据通过系统调用(如recvrecvfrom)从内核空间复制到用户空间的应用程序。

 零拷贝:避免了数据在用户空间和内核空间之间的多次拷贝,减少了数据传输的总体延迟,因为数据传输过程减少了对CPU的依赖,CPU资源可以被用于其他计算任务,从而提高了系统的整体效率,零拷贝使得数据传输过程更高效,网络带宽可以得到更充分的利用。

硬件协议处理:传统网络通信需要操作系统内核参与大量的协议处理工作,包括数据包的封装、解析和校验等。RDMA技术允许这些操作在硬件级别完成,极大地减轻了CPU的工作负担。硬件级别的数据包处理通常比软件实现更快,因为它可以并行处理多个操作,并专门针对这些任务进行优化。

二、RDMA协议类型

RDMA指的是一种远程直接内存访问技术。具体到协议层面,它主要包含了Infiniband(IB),RDMA over Converged Ethernet(RoCE)和lInternet Wide Area RDMA Protocol(iWARP)三种协议。三种协议都符合RDMA标准,共享相同的上层用户接口(Vrbs),只是在不同层次上有一些差别。下图对比了这几个协议在不同层次的差异。

三、RDMA软件架构:

RDMA的软件架构在Linux系统中按层次可分为两部分,即rdma-core内核RDMA子系统,分别运行在用户态内核态。整个软件架构适用于所有类型的RDMA网卡,无论网卡硬件执行哪种RDMA协议(Infiniband、RoCE、iWARP)。

一个RDMA应用程序的部分流程:

 四、RDMA 的基本元素和操作类型

4.1 WQ&WQE

4.1.1 工作队列元素(WQE)

  • 作用WQE是RDMA硬件执行任务的指令单元。它包含了软件希望硬件执行的具体任务类型,如远程读取、远程写入、发送或接收等操作。
  • 内容每个WQE详细描述了任务的具体信息,包括数据所在的内存地址、数据长度、访问密钥(如用于保护内存区域的密钥)等。
  • 类比:在以太网方案中,描述符(Descriptor)也用于指导硬件如何处理数据包,但RDMA的WQE提供了更高级的抽象,直接指向内存区域,而不是单个数据包。

4.1.2 工作队列(WQ)

  • 作用WQ是容纳WQE的容器,类似于以太网方案中的发送/接收队列。
  • 结构WQ采用先进先出(FIFO)队列的形式,确保WQE按顺序被处理。
  • 类比:在以太网方案中,发送/接收队列用于管理待发送或待接收的数据包,而RDMA的WQ管理的是待执行的内存操作任务。

4.1.3 关系与比较

  • WQ与WQE的关系:WQ是WQE的集合,WQE是WQ中的元素。WQ管理着一系列WQE,确保它们按顺序被硬件处理。
  • 与以太网方案的比较虽然RDMA的WQ和WQE与以太网方案中的队列和描述符在功能上有相似之处,但RDMA提供了更直接的内存到内存的数据传输方式,减少了CPU的干预,从而实现了更高的性能和更低的延迟。

通过这种架构,RDMA技术能够高效地处理大规模的内存操作请求,非常适合高性能计算和数据中心等需要高速数据传输的场景。

4.2 QP(核心元素)

4.2.1 队列对(QP)

  • 定义QP是RDMA通信中的基本单元,由一对工作队列组成,即发送队列(SQ)和接收队列(RQ)。
  • 功能:QP用于管理发送和接收任务,确保数据传输的正确性和顺序。

4.2.2 发送队列(SQ)

  • 作用SQ专门用于存放发送任务的WQE。
  • 操作:发送端在需要发送数据时,会将表示发送任务的WQE放入SQ中(这种操作称为Post Send)。

4.2.3 接收队列(RQ)

  • 作用RQ专门用于存放接收任务的WQE。
  • 操作:接收端在需要接收数据时,会将表示接收任务的WQE放入RQ中(这种操作称为Post Receive),这样硬件在接收到数据后,就知道应该将数据放到内存中的哪个位置。

4.2.4 SEND-RECV流程

  • 发送端:发送端在执行发送操作时,会将发送任务的WQE放入SQ中,通知硬件执行发送操作。
  • 接收端:接收端在执行接收操作时,会将接收任务的WQE放入RQ中,通知硬件在接收到数据后,将数据放到指定的内存位置。

4.2.5 图示说明

  • 图示:下图展示了两个终端,左边的终端正在执行Post Send操作右边的终端正在执行Post Receive操作。这表明在RDMA通信中,发送和接收操作是并行进行的,且需要双方都准备好相应的队列和WQE。

4.2.6 队列对(QP)

  • 定义:在RDMA通信中,QP是基本的通信单元,它由一个发送队列(SQ)和一个接收队列(RQ)组成。QP是进程间通信的桥梁,而不是节点本身。

  • 使用每个节点上的每个进程都可以申请和使用多个QP。这些QP可以用于不同的通信目的,例如不同的数据流或不同的通信模式。

  • 连接每个本地QP可以“连接到”一个远端的QP。这种连接是通过网络建立的,使得本地QP中的发送任务能够发送到远端QP,而远端QP中的接收任务能够接收来自本地QP的数据。

  • 例子:节点A的进程2使用的QP2连接到了节点B的进程1使用的QP0。这意味着QP2中的发送任务将被发送到QP0,而QP0中的接收任务将等待来自QP2的数据。

4.2.7 QP编号(QPN)

  • 唯一标识每个节点的每个QP都有一个唯一的编号,称为QP编号(QPN)。QPN是一个整数,用于在网络中唯一标识一个QP。

  • 作用:通过QPN,通信双方可以准确地识别和定位到对方节点上的QP,从而确保数据能够正确地发送到目标QP。

4.2.8 通信流程

  • 建立连接:在进行RDMA通信之前,通信双方需要通过某种机制(如IBA或RoCE协议)交换QP信息,包括QPN和QP的状态。

  • 数据传输一旦QP连接建立,数据传输就可以通过这些QP进行。发送端将数据放入SQ,接收端将接收位置信息放入RQ,硬件根据这些信息直接在内存之间传输数据,无需CPU干预。

4.3 CQ

Completion Queue(完成队列,简称CQ)和CQE(Completion Queue Element,完成队列元素)的描述十分准确。

4.3.1 完成队列(CQ)

  • 定义:CQ是RDMA通信中的一个重要组成部分,它被设计来存放由硬件生成的完成报告,这些报告被称为CQE。

  • 功能CQ的主要作用是让软件知道其提交给硬件的工作请求(即WQE)何时被完成,以及完成的状态(成功或失败)。

4.3.2 完成队列元素(CQE)

  • 定义:CQE是CQ中的元素,它包含了某个WQE的完成信息,可以被视为硬件对软件的一种反馈。

  • 关系:每个CQE都与一个特定的WQE有关,表明该WQE的执行结果。硬件在完成一个WQE之后,会生成一个相应的CQE并放入CQ中。

  • 内容:一个CQE通常会包含以下信息:关联的WQE的标识、操作的状态(成功或失败)、如果失败了,失败的原因是什么,以及其他可能的信息。

4.3.3 一般流程

  • 提交任务:软件通过将WQE放入SQ或RQ来提交一个任务。

  • 完成任务:硬件根据WQE中的信息执行任务,然后生成一个CQE,包含该任务的完成信息,并将CQE放入CQ。

  • 检查结果:软件可以检查CQ,查看其提交的任务的完成情况。如果发现某个任务失败,还可以通过查看相应的CQE来了解失败的原因。

4.4 RDMA Write操作(典型操作)

4.4.1 RDMA WRITE操作

  • 基本定义RDMA WRITE操作允许一端的应用程序直接写入另一端的内存,而无需远端的CPU介入。这种操作的效率非常高,因为它减少了网络通信中的CPU使用和中断。

  • 单端操作这是一种单端操作,即只有数据的发送方(源端)需要主动执行操作,而接收方(目标端)的CPU并不参与数据的接收过程,也不会被通知数据的到达。这一点是RDMA技术区别于传统网络通信的显著特征。

4.4.2 地址转换

  • 虚拟地址操作操作的发起端通过虚拟地址来指定要写入的数据和目标内存的位置。这使得上层应用能够非常方便地控制数据的发送。

  • 地址转换虽然应用程序使用虚拟地址,但实际的内存访问需要物理地址。这一转换过程由RDMA网卡(也称为RNIC)负责。RNIC在执行数据传输前,会把虚拟地址转换为物理地址,确保数据能够正确地写入远端机器的物理内存。

4.4.3 实际应用和性能优势

  • 低延迟高效率:由于远端CPU不参与数据接收过程,RDMA WRITE操作可以实现极低的延迟和高吞吐量,这对于需要高性能计算和数据密集型应用(如数据中心和大规模分布式系统)非常有利。

  • 内存一致性:尽管远端CPU不直接参与,RDMA协议仍然能够保证内存的一致性和数据的正确性,通过硬件级别的同步机制来实现。

 4.5 Memory Region

4.5.1 Memory Region(MR)

  • 定义:MR是预定义的内存区域,它将一段虚拟内存映射到对应的物理内存。每个MR都有一个唯一标识符(Key或R_Key),这个标识符在RDMA操作中用来验证访问权限。

4.5.2 解决问题

   1. 虚拟地址到物理地址的转换

  • 当应用程序通过虚拟地址进行RDMA操作时,RDMA网卡(RNIC)需要知道相应的物理地址才能进行数据读写。使用MR时,RDMA网卡通过与操作系统内核协作,预先获得这段内存的虚拟地址到物理地址的映射。
  • 在MR创建时,操作系统的内存管理单元(MMU)会参与到MR的初始化,确保每个虚拟地址都能正确映射到物理地址。这样,当RDMA操作发生时,网卡能够直接使用这些信息进行高效的数据传输。

  2. 安全控制和访问权限验证

  • 为了防止恶意软件通过指定非法的虚拟地址来访问或篡改关键系统内存,MR在创建时需进行权限设置和验证。
  • 每个MR都与一个键(Key)关联,这个键在RDMA操作时需要被提供并验证。如果操作的Key与MR的Key不匹配,则操作将被拒绝,这样可以保证只有授权的操作才能访问特定的内存区域。
  • 操作系统在创建MR时可以对这段内存区域进行保护设置,防止它包含敏感或关键的系统数据。

4.5.3 实际应用

在实际应用中,通过合理配置和使用MR,可以确保RDMA操作的高效性和安全性。系统管理员或应用开发者需确保MR按需正确设置,既满足性能要求又确保系统安全。RDMA技术的这种设计使其非常适用于需要快速、直接内存访问的场景,如高性能计算和大规模存储系统。

4.6 RDMA各种元素的实体形式

所有的RDMA元素在实际方案中都以数据的形式体现、管理和使用。

下图简单展示了这些元素对应的数据的存放位置以及它们之间的关系。

五、RDMA 设计思路 

5.1 应用程序的执行流程和每一步的主要工作

 5.2 设计思路

5.2.1 初始化和配置等低频操作可以进入内核态执行

  • 目的和逻辑初始化和配置操作,如设置保护域(PD)、创建队列对(QP)、配置内存区域(MR)等,是设置RDMA环境的基础步骤。这些操作通常频率较低,但需要高权限和精确控制。
  • 内核态的优势在内核态执行这些操作可以利用操作系统提供的安全和管理机制。例如,操作系统能够管理和保护内存访问,防止非法访问,并且可以对硬件资源进行有效的配置和管理。

5.2.2 数据传输等高频操作旁路内核

  • 目的和逻辑:数据传输是RDMA的核心功能,特点是频繁且对延迟敏感。直接在用户态执行数据传输操作可以极大地减少上下文切换和系统调用的开销,从而降低延迟和提高吞吐量。
  • 旁路内核的实现:通过在用户空间提供直接访问网络接口和硬件的能力,避开传统的内核网络栈处理。这通常通过操作系统提供的特定API(如Linux的ibverbs库)实现,使得应用程序能直接与RDMA硬件交互。

5.2.3 独立的QP、CQ资源保证多线程并发

  • 目的和逻辑在RDMA中,每个队列对(QP)和完成队列(CQ)是执行数据传输和接收操作的基本单位。为每个连接或每个线程配置独立的QP和CQ,可以提高并发性,并减少资源争用。
  • 多线程并发的优势:当多个线程或多个应用同时进行RDMA操作时,各自使用独立的资源(QP和CQ)可以避免交互影响和锁竞争,提高系统的整体性能和响应速度。

5.2.4 小结

这三点设计思路共同体现了RDMA技术的高效性和并发性,是RDMA在高性能计算和大规模数据中心得以广泛应用的技术基础。通过智能地分配任务至内核态和用户态,以及优化资源管理,RDMA能够显著提高数据传输的效率并减少延迟,同时保证在高并发环境下的稳定性和可靠性。

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

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

相关文章

单机、集群、分布式服务器比较:

1. 单机服务器的瓶颈: 单机服务器:一台服务器独立运行一个工程所需的全部的业务模块 受限于服务器硬件资源,所承受用户并发量受限,32位linux操作系统最大并发量为两万任一模块的变动和修改,都会导致整个项目代码重新编…

移动端如何离线使用GPT

在移动端离线使用GPT,只需要一个app:H2O AI Personal GPT 是H2OAI上架的一款app,可离线使用,注重数据隐私,所有数据都只存储在本地。对H2OAI感兴趣的伙伴,可移步:https://h2o.ai 该app支持的模…

华为od 100问 持续分享6-入职体检

我是一名软件开发培训机构老师,我的学生已经有上百人通过了华为OD机试,学生们每次考完试,会把题目拿出来一起交流分享。 重要:2024年5月份开始,考的都是OD统一考试(D卷),题库已经整…

如何学习Kafka:糙快猛的大数据之路(快速入门到实践)

在大数据开发的世界里,Kafka 无疑是一个不可或缺的重要角色。作为一个分布式流处理平台,它以其高吞吐量、可靠性和可扩展性而闻名。 目录 糙快猛学习法则Kafka 是什么?我的 Kafka 学习故事第一步: 快速上手第二步: 生产和消费消息第三步: 编写简单的生产者和消费者程序 深入Ka…

达梦数据库 DISQL连接数据库与执行SQL、脚本的方法

DISQL连接数据库与执行SQL、脚本的方法 1.DISQL介绍2.DISQL连接数据库的方法2.1 本地连接2.2 远程连接2.3 CONN连接 3.执行SQL、脚本的方法3.1 通过DISQL登录后在字符界面3.2 启动DISQL时运行脚本3.3 进入DISQL后,通过start命令运行脚本3.4 使用EDIT命令编辑脚本 1.…

(02)Unity使用在线AI大模型(调用Python)

目录 一、概要 二、改造Python代码 三、制作Unity场景 一、概要 查看本文需完成(01)Unity使用在线AI大模型(使用百度千帆服务)的阅读和实操,本文档接入指南的基础上使用Unity C#调用百度千帆大模型,需要…

【开发踩坑】使用PageHelper工具正常sql后面多无关语句

背景 SQL日志打印出现了脏东西: 本来结束的 where muc.code ?;后面凭空多出了一个 LIMIT语句 ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your …

【Spark On Hive】—— 基于电商数据分析的项目实战

文章目录 Spark On Hive 详解一、项目配置1. 创建工程2. 配置文件3. 工程目录 二、代码实现2.1 Class SparkFactory2.2 Object SparkFactory Spark On Hive 详解 本文基于Spark重构基于Hive的电商数据分析的项目需求,在重构的同时对Spark On Hive的全流程进行详细的…

Unity点击生成节点连线

Unity点击生成节点连线 效果 2.主要代码 Test_Line 控制类 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems;public class Test_Line : MonoBehaviour {public GameObject qiu_prefab;public List<Game…

基于 CNN(二维卷积Conv2D)+LSTM 实现股票多变量时间序列预测(PyTorch版)

前言 系列专栏:【深度学习&#xff1a;算法项目实战】✨︎ 涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域&#xff0c;讨论了各种复杂的深度神经网络思想&#xff0c;如卷积神经网络、循环神经网络、生成对…

android13读取cpu频率,并调整频率

总纲 android13 rom 开发总纲说明 目录 1.前言 2.频率类型 3.获取cpu可以调节的频率 4.获取当前频率 5.设置频率 6.最后我们写个脚本,来实现,可以通过参数获取所有cpu的频率,以及设置最大最小频率 6.1 获取cpu频率 6.2 设置最大cpu频率 6.3 设置最小 7.彩蛋 1.前…

敏捷开发笔记(第12章节)--接口隔离原则(ISP)

目录 1&#xff1a;PDF上传链接 12.1&#xff1a;接口污染 12.2&#xff1a;分离客户就是分离接口 12.3&#xff1a;接口隔离原则&#xff08;ISP&#xff09; 12.4&#xff1a;类接口与对象接口 12.4.1&#xff1a;使用委托分离接口 12.4.2&#xff1a;使用多重继承分离接口 …

基于JAVA+SpringBoot+Vue+uniApp的校园日常作品商品分享小程序

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、SpringCloud、Layui、Echarts图表、Nodejs、爬…

为什么精酿人士选择FENDI CLUB啤酒

FENDI CLUB啤酒作为云仓酒庄平台的精酿啤酒自有品牌&#xff0c;平台提供以技术咨询与服务为核心的全产业链精酿产品解决方案&#xff0c;帮助啤酒代理商提高产品质量&#xff0c;树立优质品牌&#xff0c;推广精酿文化&#xff0c;促进精酿发展&#xff0c;力争成为中国本土品…

Leetcode3208. 交替组 II

Every day a Leetcode 题目来源&#xff1a;3208. 交替组 II 解法1&#xff1a;环形数组 把数组复制一份拼接起来&#xff0c;和 3101 题一样&#xff0c;遍历数组的同时&#xff0c;维护以 i 为右端点的交替子数组的长度 cnt。 如果 i ≥ n 且 cnt ≥ k&#xff0c;那么 i…

基于springboot+vue+uniapp的开放实验室预约管理系统

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

算法第九天:leetcode59.螺旋矩阵II

给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]]示例 2&#xff1a; 输入&#xff1a;n 1 输出&am…

如何高效删除 JavaScript 数组中的重复元素?

在日常编程中&#xff0c;我们经常会遇到数组去重的问题。今天&#xff0c;我们就来聊聊如何用JavaScript来优雅地解决这个问题。 问题描述 给定一个包含重复元素的数组&#xff0c;我们希望创建一个新的数组&#xff0c;其中只包含原始数组中的唯一值。例如&#xff0c;如果我…

十二、数组(2)

1.冒泡排序数组&#xff08;升序&#xff09; 冒泡排序&#xff1a;将一个整型数组排序&#xff08;升序&#xff09; 例&#xff1a; 10 9 8 7 6 5 4 3 2 1 9 10 8 7 6 …

Android11 framework 禁止三方应用开机自启动

Android11应用自启动限制 大纲 Android11应用自启动限制分析验证猜想&#xff1a;Android11 AOSP是否自带禁止三方应用监听BOOT_COMPLETED​方案禁止执行非系统应用监听到BOOT_COMPLETED​后的代码逻辑在执行启动时判断其启动的广播接收器一棍子打死方案&#xff08;慎用&#…