RabbitMQ简述

RabbitMQ 是一个开源的 消息代理(Message Broker) 软件,实现了 高级消息队列协议(AMQP),用于在分布式系统中存储、转发消息,支持异步通信、解耦服务、负载均衡和消息缓冲。

核心概念

Producer(生产者):发送消息的应用。
Consumer(消费者):接收消息的应用。
Queue(队列):存储消息的缓冲区,遵循 FIFO(先进先出)。
Exchange(交换机):接收生产者消息并路由到队列(根据规则)。
Binding(绑定):定义交换机和队列之间的关联规则。
Message(消息):包含有效载荷(数据)和元数据(如路由键、头信息)。

交换机类型(Routing Strategies)

直连交换机(Direct Exchange)

Direct:精确匹配路由键(如点对点通信)。

  • 根据消息的routing key精确匹配队列
  • 常用于单播(unicast)消息路由
  • 典型应用场景:订单处理(不同订单类型路由到不同队列)

扇形交换机(Fanout Exchange)

Fanout:广播到所有绑定的队列(发布/订阅模式)。

  • 将消息广播到所有绑定的队列
  • 忽略routing key
  • 典型应用场景:广播通知、事件发布

主题交换机(Topic Exchange)

Topic:基于通配符匹配路由键(灵活的路由)。

  • 根据通配符匹配routing key
  • 支持*(匹配一个单词)和#(匹配零个或多个单词)
  • 典型应用场景:基于多维度路由(如日志级别.应用名称)

头交换机(Headers Exchange)

Headers:通过消息头属性路由(而非路由键)。

  • 根据消息头(header)属性匹配
  • 忽略routing key
  • 支持x-match参数(all需全部匹配,any只需匹配一个)

交换机属性

创建交换机时可设置以下主要属性:
Name:交换机名称
Type:交换机类型(direct, fanout, topic, headers)
Durability:是否持久化(重启后是否保留)
Auto-delete:当所有队列都解除绑定后是否自动删除
Arguments:额外参数(如alternate-exchange等)

模式

模式交换机类型核心机制典型应用场景
简单模式默认交换机直接队列绑定单任务异步处理
工作队列默认交换机多消费者竞争并行任务处理
发布/订阅Fanout广播到所有队列事件通知
路由模式Direct精确匹配路由键选择性日志分发
主题模式Topic通配符匹配路由键多维度消息分类
RPC默认交换机回调队列+关联ID同步远程调用
头部交换机Headers键值对匹配复杂条件路由
死信队列任意类型(DLX)TTL/拒绝触发异常消息处理
延迟队列Delayed Message插件延迟投递定时任务/超时控制

简单模式

在这里插入图片描述
简单队列不介绍,直接看工作队列

工作队列

在这里插入图片描述

创建队列

创建一个名为xiri.queue的队列

在这里插入图片描述

消费者代码

模拟2个消费者互相抢消息

@Component
public class SpringRabbitListener 
{@RabbitListener(queues = {"xiri.queue"})public void listener1(String mes){System.out.println("消费者1接受消息:"+mes);}@RabbitListener(queues = {"xiri.queue"})public void listener2(String mes){System.out.println("消费者2接受消息:"+mes);}
}

生产者代码

模拟50条消息

@SpringBootTest
public class ProducerTest 
{@AutowiredRabbitTemplate rabbitTemplate;@Testvoid WorkQueueSent(){//队列名称String queueName = "xiri.queue";for (int i = 1; i <= 50; i++) {//发送消息rabbitTemplate.convertAndSend(queueName,"消息-"+i);	}}
}

运行结果

由此发现默认情况下,是轮询投递消息,并没有考虑到消费者已经处理完了消息,造成消息堆积
在这里插入图片描述

消息堆积处理方案(能者多劳)

设置每次只能给消费者投递1次消息,处理完成后才能获取下一个消息

  1. 修改yml配置文件
spring:rabbitmq:host: 127.0.0.1   #ipport: 5672  #端口virtual-host: /xiri   #虚拟主机username: xiri  #账号password: 123   #密码listener:simple:prefetch: 1 #每次只能获取一条消息,处理完成才能获取下一个消息
  1. 修改消费者代码
    给代码加上等待时间进行模拟测试
@Component
public class SpringRabbitListener 
{@RabbitListener(queues = {"xiri.queue"})public void listener1(String mes) throws InterruptedException {System.out.println("消费者1接受消息:"+mes);Thread.sleep(20);}@RabbitListener(queues = {"xiri.queue"})public void listener2(String mes) throws InterruptedException {System.out.println("消费者2接受消息:"+mes);Thread.sleep(100);}
}
  1. 测试结果
    消费者1处理消息快,处理消息多,实现能者多劳
    在这里插入图片描述

发布/订阅

在这里插入图片描述

控制台设置

设置一个fanout交换机
在这里插入图片描述
设置两个队列
在这里插入图片描述
绑定2个队列
在这里插入图片描述

消费者

在消费者服务写两个消费者方法模拟,分别监听队列1和队列2

@Component
public class SpringRabbitListener 
{@RabbitListener(queues = {"xiri.queue1"})public void listener1(String mes) throws InterruptedException {System.out.println("消费者1接受消息:"+mes);}@RabbitListener(queues = {"xiri.queue2"})public void listener2(String mes) throws InterruptedException {System.out.println("消费者2接受消息:"+mes);}
}

生产者

生产者向交换机发送消息

@SpringBootTest
public class ProducerTest 
{@AutowiredRabbitTemplate rabbitTemplate;@Testvoid sent(){//队列名称String exchange = "xiri.fanout";//发送消息rabbitTemplate.convertAndSend(exchange,null,"消息");//routingKey没有设置,可以为空}
}

运行结果

在这里插入图片描述

路由模式

直连交换机(Direct Exchange)会根据规则路由到指定的队列

控制台设置

创建类型为direct,名称为xiri.direct交换机
在这里插入图片描述
创建2个队列,名字分别为direct.queue1、direct.queue2
在这里插入图片描述
进行绑定
direct.queue1绑定key1
direct.queue2绑定key2
在这里插入图片描述

消费者

@Component
public class SpringRabbitListener 
{@RabbitListener(queues = {"direct.queue1"})public void listener1(String mes) throws InterruptedException {System.out.println("消费者1接受消息:"+mes);}@RabbitListener(queues = {"direct.queue2"})public void listener2(String mes) throws InterruptedException {System.out.println("消费者2接受消息:"+mes);}
}

生产者

@SpringBootTest
public class ProducerTest 
{@AutowiredRabbitTemplate rabbitTemplate;@Testvoid sent(){//队列名称String exchange = "xiri.direct";//发送消息rabbitTemplate.convertAndSend(exchange,"key1","消息1");rabbitTemplate.convertAndSend(exchange,"key1","消息2");rabbitTemplate.convertAndSend(exchange,"key2","消息3");}
}

运行结果

在这里插入图片描述

主题模式

直连交换机(Direct Exchange) 和 主题交换机(Topic Exchange)类似,区别在于Routing key可以是多个单词列表以 .(点) 分割

控制台设置

创建类型为topic,名为xiri.topic的交换机
在这里插入图片描述
创建队列
在这里插入图片描述
交换机绑定队列在这里插入图片描述

消费者

@Component
public class SpringRabbitListener 
{@RabbitListener(queues = {"topic.queue1"})public void listener1(String mes) throws InterruptedException {System.out.println("消费者1接受消息:"+mes);}@RabbitListener(queues = {"topic.queue2"})public void listener2(String mes) throws InterruptedException {System.out.println("消费者2接受消息:"+mes);}
}

生产者

@SpringBootTest
public class ProducerTest 
{@AutowiredRabbitTemplate rabbitTemplate;@Testvoid sent(){//队列名称String exchange = "xiri.topic";//发送消息rabbitTemplate.convertAndSend(exchange,"topic.key1","消息1");rabbitTemplate.convertAndSend(exchange,"topic.key2","消息2");rabbitTemplate.convertAndSend(exchange,"topic.key.node1","消息3");}
}

运行结果

根据通配符发到消费者
在这里插入图片描述

注解声明队列和交换机

在消费者端,通过 @RabbitListener 注解自动声明队列并绑定到交换机

@Component
public class SpringRabbitListener 
{//基于注解来声明队列和交换机,并且绑定@RabbitListener(bindings = {@QueueBinding(value = @Queue(value = "direct.queue1", durable = "true"),	//设置队列,并且持久化exchange = @Exchange(value = "xiri.direct",type = ExchangeTypes.DIRECT),	//设置交换机和类型key = {"key1"}	//设置路由)})public void listener1(String mes) throws InterruptedException {System.out.println("消费者1接受消息:"+mes);}
}

消息转换器

转换成json格式传输
消费者和生产者都需要创建bean

创建Bean

import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitConverter 
{@Beanpublic MessageConverter messageConverter(){return new Jackson2JsonMessageConverter();}
}

这样数据就是以JSON格式传输的
获取消息
在这里插入图片描述

消息丢失问题

生产者发送消息丢失

生产者发送消息到 RabbitMQ 服务器时,由于网络问题或 RabbitMQ 服务崩溃,消息未到达交换机

解决方案

1. 生产者重试机制

通过配置重试机制,但是SpringAMQP是阻塞的,如果对性能有要求不能使用,这个只是对连接进行的重试,而不是消息失败的重试

spring:rabbitmq:host: 127.0.0.1   #ipport: 5672  #端口virtual-host: /xiri   #虚拟主机username: xiri  #账号password: 123   #密码connection-timeout: 1s #超时时间template:retry:enabled: true #开启超时重试机制initial-interval: 1000ms #失败后初始等待时间multiplier: 1 #失败后下次等待时长倍数=initial-interval*multipliermax-attempts: 3 #最大重试次数

测试效果,故意将网络故障,造成超时重试3次
在这里插入图片描述

2. 生产者确认

RabbitMQ 提供 ConfirmCallback 机制,确认消息是否成功到达交换机。
如果对消息可靠性要求不高,不需要开启确认机制,因为会影响性能
生产者yml文件配置

spring:rabbitmq:host: 127.0.0.1   #ipport: 5672  #端口virtual-host: /xiri   #虚拟主机username: xiri  #账号password: 123   #密码connection-timeout: 1s #超时时间template:retry:enabled: true #开启超时重试机制initial-interval: 1000ms #失败后初始等待时间multiplier: 1 #失败后下次等待时长倍数=initial-interval*multipliermax-attempts: 3 #最大重试次数publisher-confirm-type: correlated  # 开启异步确认publisher-returns: true # 开启路由失败回调

以下为以上内容中关键的配置信息

publisher-confirm-type: correlated  # 开启异步确认
publisher-returns: true # 开启路由失败回调

生产者代码配置

// Spring AMQP 配置
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) 
{RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);rabbitTemplate.setMandatory(true); // 开启强制回调// 设置 ConfirmCallbackrabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {if (ack) {System.out.println("消息到达交换机,ID: " + correlationData.getId());} else {System.err.println("消息未到达交换机,原因: " + cause);}});// 设置 ReturnsCallbackrabbitTemplate.setReturnsCallback(returned -> {System.err.println("消息未路由到队列: " + returned.getMessage());});return rabbitTemplate;
}

生产者测试

@SpringBootTest
public class ProducerTest 
{@AutowiredRabbitTemplate rabbitTemplate;@Testvoid sent(){//队列名称String exchange = "xiri.direct";//设置消息唯一编号CorrelationData id = new CorrelationData(UUID.randomUUID().toString());//发送消息rabbitTemplate.convertAndSend(exchange,"key","消息",id);}
}

消息结果
在这里插入图片描述

3. 数据持久化

RabbitMQ默认将数据保存在内存当中,如果宕机了,消息就会丢失,还会造成内存积压,引发阻塞问题
实现数据持久化三个方面:交换机持久化、队列持久化、消息持久化
spring发送消息默认就是持久的
设置非持久化

@SpringBootTest
public class ProducerTest 
{@AutowiredRabbitTemplate rabbitTemplate;@Testvoid sent() {//队列名称String exchange = "xiri.direct";//设置消息唯一编号CorrelationData id = new CorrelationData(UUID.randomUUID().toString());//发送消息rabbitTemplate.convertAndSend(exchange, "key", "消息", new MessagePostProcessor() {@Overridepublic Message postProcessMessage(Message message) {message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT);//发送持久化消息return message;}});}
}

以下已经设置为1,表示非持久化模式
在这里插入图片描述

4. lazy queue

Lazy Queue 是 RabbitMQ 的一种特殊队列模式,它会尽可能将消息存储在磁盘,而不是内存中,从而减少内存使用,适合处理大量消息且消费较慢的场景
3.6.0(初始引入)
首次支持 Lazy Queue,允许消息直接存储到磁盘,减少内存占用。
3.12.0(默认模式)
从该版本开始,Lazy Queue 成为所有队列的默认模式,官方推荐升级到该版本或手动启用 Lazy 模式1。

消费者消息丢失问题

解决方案

1.确认机制

SpringAMQP消息确认机制有三种处理方式:

  1. none 不处理
  2. manual 手动处理,需要在业务代码中调用api
  3. auto 自动处理,利用aop处理,对代码没有破坏性
    当业务出现异常时,会自动返回nack
    如果是消息处理或校验异常,自动返回reject

开启消费者确认机制为auto,有spring确认消息处理完成后返回ack,异常返回nack

spring:rabbitmq:listener:simple:acknowledge-mode: auto  #none:关闭ack,manual:手动ack,auto:自动ack
2.重试机制

在 Spring AMQP 的 RabbitMQ 配置中,stateless 是消费者重试机制(retry)的一个参数,用于控制重试时的状态管理方式
stateless=true(默认)

  1. 每次重试都是无状态的,即不保留前一次尝试的上下文(如数据库事务、Spring Session 等)。
  2. 适用场景:普通消息处理,无需依赖前一次重试的状态。
  3. 性能更好:因为不需要维护状态。

stateless=false

  1. 重试时会保留状态(如事务、Session 等),确保多次重试在同一个上下文中执行。
  2. 适用场景:需要事务一致性的操作(如支付处理)。
  3. 性能较低:因为需要维护状态。

开启重试机制

spring:rabbitmq:listener:simple:prefetch: 1 #每次只能获取一条消息,处理完成才能获取下一个消息retry:enabled: true #开启消费者重试机制initial-interval: 1000ms #失败后初始等待时间multiplier: 1 #失败后下次等待时长倍数=initial-interval*multipliermax-attempts: 3 #最大重试次数stateless: true #true为无状态,false为有状态。决定重试时是否保持消费者状态(如事务、Session等)

重试多次依然失败处理策略
在开启重试模式后,重试次数耗尽依然失败,则需要有MessageRecoverer接口来处理,它有三种实现:

实现类行为适用场景
RejectAndDontRequeueRecoverer(默认)直接拒绝消息(reject),且不重新入队,消息可能丢失或进入死信队列(若配置)13非关键消息,允许丢弃
ImmediateRequeueMessageRecoverer立即将消息重新放回队列(nack + requeue=true),可能导致无限循环临时性错误(如网络抖动)
RepublishMessageRecoverer(推荐)将消息重新发布到指定的异常交换机和队列,供人工或后续处理关键业务,需

使用第三种方式演示
开启消费者失败重试机制,并设置MessageRecoverer,多次重试无效后将消息投递到异常交换机,交由人工处理问题
消费者ymy配置

spring:rabbitmq:listener:simple:retry:enabled: true #开启消费者重试机制

消费者配置

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.retry.MessageRecoverer;
import org.springframework.amqp.rabbit.retry.RepublishMessageRecoverer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
//这个配置需要开启重试机制才会开启
@ConditionalOnProperty(prefix = "spring.rabbitmq.listener.simple.retry",name="enabled",havingValue = "true")
public class ErrorConfig
{@Beanpublic DirectExchange errorExchange(){return new DirectExchange("error.direct");}@Beanpublic Queue errorQueue(){return new Queue("error.queue");}@Beanpublic Binding errorBinding(DirectExchange errorExchange,Queue errorQueue){//队列绑定交换机return BindingBuilder.bind(errorQueue).to(errorExchange).with("error");}@Beanpublic MessageRecoverer messageRecoverer(RabbitTemplate rabbitTemplate){return new RepublishMessageRecoverer(rabbitTemplate,"error.direct","error");}
}

效果
将异常信息和消息全部转到了error.queue
在这里插入图片描述

业务层幂等设计

  1. 数据库唯一约束
  • 例如订单表对 order_id 设置唯一索引,重复插入会报错。
    Redis 原子操作
  • 用 SETNX 或分布式锁标记已处理的消息。
  1. 消息去重
  • 生产者生成唯一 ID,发送消息时携带 correlationId,消费者记录已处理的 ID。
  • 消费者记录消息 ID,用 Redis 或数据库存储已处理的消息 ID。

延迟消息

1.死信交换机

利用死信队列(DLX)+ TTL 实现延迟消息
死信队列(DLX):死信会被路由到指定的死信交换机(DLX),再进入死信队列,由消费者处理
消息设置 TTL(Time To Live):消息或队列可以设置过期时间(TTL),到期后消息会变成“死信”

在这里插入图片描述

消费者

声明队列

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class DlxConfig 
{@Beanpublic DirectExchange xiriExchange(){return new DirectExchange("xiri.direct",true,false);}@Beanpublic Queue xiriQueue(){return QueueBuilder.durable("xiri.queue").withArgument("x-dead-letter-exchange", "dlx.direct").withArgument("x-dead-letter-routing-key","dlx.key").build();}@Beanpublic Binding xiriBinding() {return BindingBuilder.bind(xiriQueue()).to(xiriExchange()).with("xiri.key");}
}

消费

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;@Component
public class SpringRabbitListener 
{@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "dlx.queue", durable = "true"),exchange = @Exchange(name = "dlx.direct", type = ExchangeTypes.DIRECT),key = "dlx.key" // 死信路由键))public void listener(String mes) throws InterruptedException {System.out.println(LocalDateTime.now() +" 死信接受消息:"+mes);}
}
生产者
import org.junit.jupiter.api.Test;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.time.LocalDateTime;@SpringBootTest
public class ProducerTest 
{@AutowiredRabbitTemplate rabbitTemplate;@Testvoid sent(){//队列名称String exchange = "xiri.direct";//发送消息rabbitTemplate.convertAndSend(exchange, "xiri.key", "消息", new MessagePostProcessor() {@Overridepublic Message postProcessMessage(Message message) throws AmqpException {//设置过期时间(5秒)message.getMessageProperties().setExpiration("5000");return message;}});System.out.println(LocalDateTime.now() +" 发送消息");}
}
结果

在这里插入图片描述
5秒后收到消息
在这里插入图片描述

缺点: 消息排序问题:如果队列中有不同 TTL 的消息,RabbitMQ 只会检查队头消息的 TTL,可能导致后进队的消息先过期

2.RabbitMQ延迟插件

使用 rabbitmq-delayed-message-exchange 插件
RabbitMQ 官方提供的插件,通过 自定义交换机类型(x-delayed-message) 实现真正的延迟投递,消息按延迟时间排序,到期后才会被路由到目标队列

  1. 下载插件(需匹配 RabbitMQ 版本):
    插件下载地址:https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases
  2. 将下载的文件放到RabbitMQ的plugins目录里面
  3. 启用插件
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
  1. 重启RabbitMQ

关闭

rabbitmq-service.bat stop

启动

rabbitmq-server start

消费者

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;@Component
public class SpringRabbitListener 
{//延迟队列,关键点在交换机设置delayed属性为true@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "xiri.queue", durable = "true"),exchange = @Exchange(name = "xiri.direct", type = ExchangeTypes.DIRECT,delayed = "true"),key = "xiri.key"))public void listener1(String mes) throws InterruptedException {System.out.println(LocalDateTime.now()+" 消费者接受消息:"+mes);}
}

生产者

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.time.LocalDateTime;@SpringBootTest
public class ProducerTest 
{@AutowiredRabbitTemplate rabbitTemplate;@Testvoid sent(){//队列名称String exchange = "xiri.direct";//发送消息rabbitTemplate.convertAndSend(exchange,"xiri.key","消息",message -> {message.getMessageProperties().setDelayLong(5000L);//设置5秒过去return message;});System.out.println(LocalDateTime.now()+" 发送消息");}
}

结果

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

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

skywalking应用性能监控

1.skywalking描述 官方文档 SkyWalking 是一个开源的可观测性平台&#xff0c;用于收集、分析、汇总和可视化来自服务及云原生基础设施的数据。SkyWalking 为维护分布式系统的清晰视图提供了简便的方法&#xff0c;即使是在跨云环境中也能做到。它是一款专为云原生、基于容器的…

如何彻底清除服务器上的恶意软件与后门

清除服务器上的恶意软件与后门 是确保服务器安全的关键步骤。恶意软件和后门可能导致数据泄露、性能下降&#xff0c;甚至服务器被攻击者完全控制。以下是彻底清除恶意软件与后门的详细指南&#xff0c;包括 检测、清理、修复与预防 的步骤。1. 彻底清除恶意软件与后门的步骤1.…

Linux和Windows基于V4L2和TCP的QT监控

最近工作需要用QT做一个网络摄像头测试&#xff0c;简单记录&#xff1a;服务端&#xff0c;主机配置为Ubuntu&#xff0c;通过端口12345采集传输MJPEG格式图片windows客户端&#xff0c;QT Creator通过ip地址连接访问提前准备服务端需要安装QT5sudo apt-get install qt5-defau…

yolo格式

labelimg中的格式yolo格式id 框中心点X对于总图片的比例 框中心点Y对于总图片的比例 框X总长度对于总图片的比例 框Y总长度对于总图片的比例

Day 8-zhou R包批量安装小补充!!!

BiocManager::install(c(“S4Vectors”, “BiocGenerics”)) 以下是使用BiocManager安装S4Vectors和BiocGenerics包的详细步骤。这些步骤基于最新的Bioconductor和R版本&#xff08;R 4.5&#xff09;。 安装步骤安装BiocManager 如果你还没有安装BiocManager&#xff0c;可以使…

电商项目_核心业务_数据归档

无论采用哪种存储系统&#xff0c;数据查询的耗时取决于两个因素查找的时间复杂度数据总量查找的时间复杂度又取决于查找算法数据存储结构以Mysql存储的订单数据为例&#xff0c;随着业务的发展&#xff0c;数据量越来越大&#xff0c;对一些历史归档数据的查询&#xff0c;如果…

第十讲:stack、queue、priority_queue以及deque

目录 1、stack 1.1、stack的使用 1.2、stack的OJ题 1.2.1、最小栈 1.2.2、栈的压入弹出序列 1.2.3、逆波兰表达式求值 1.3、stack的模拟实现 2、queue 2.1、queue的使用 2.2、queue的OJ题 2.2.1、二叉树的层序遍历 2.3、queue的模拟实现 3、priority_queue 3.1、…

如何思考一个动态规划问题需要几个状态?

如何思考一个动态规划问题需要几个状态&#xff1f;第一步&#xff1a;思考 角色第二步&#xff1a;考虑 过去的影响第三步&#xff1a;画出状态转移图第四步&#xff1a;写出状态转移方程第五步&#xff1a;验证是否能覆盖所有路径 边界几个常见题目总结&#xff1a;第一步&a…

【每天一个知识点】生成对抗聚类(Generative Adversarial Clustering, GAC)

&#x1f4d8; 生成对抗聚类&#xff08;Generative Adversarial Clustering, GAC&#xff09; 一、研究背景与动机 聚类是无监督学习中的核心任务。传统方法如 K-means、GMM、DBSCAN 等难以适应高维、非线性、复杂结构数据。 生成对抗聚类&#xff08;GAC&#xff09; 融合…

Qt 窗口 工具栏QToolBar、状态栏StatusBar

每日激励&#xff1a;“不设限和自我肯定的心态&#xff1a;I can do all things。 — Stephen Curry” 绪论​&#xff1a; 一段时间没有更新&#xff0c;这段时间一直在忙各种事情&#xff0c;后续将再次上路持续更新C相关知识 本章将继续前面的QT篇章&#xff0c;本章主要讲…

FFmpeg——参数详解

FFmpeg参数详解一、基本命令结构1.1、查询参数1.1.1、version1.1.2、buildconf1.1.3、devices1.1.4、formats1.1.5、muxers1.1.6、demuxers1.1.7、codecs1.1.8、decoders1.1.9、encoders1.1.10、bsfs1.1.11、protocols1.1.12、filters1.1.13、pix_fmts1.1.14、layouts1.1.15、s…

流媒体传输:RTSP传输详解(包含RTP,RTCP,RTSP详解)

一、什么是 RTSP​协议 1.1 RTSP 协议简介​ RTSP&#xff0c;全称实时流传输协议&#xff08;Real Time Streaming Protocol&#xff09;&#xff0c;是一种位于应用层的网络协议。它主要用于在流媒体系统中控制实时数据&#xff08;如音频、视频等&#xff09;的传输&#…

Python学习-----1.认识Python

目录 前言 1.关于Python博客前期的内容 2.计算机基础概念 2.1.什么是计算机? 2.2.什么是编程&#xff1f; 2.3.编程语言有哪些&#xff1f; 3.Python背景知识 3.1.Python是怎么来的&#xff1f; 3.2.Python都可以用来干什么&#xff1f; 3.3.Python的优缺点 3.4.Py…

MongoDB频繁掉线频繁断开服务的核心原因以及解决方案-卓伊凡|贝贝|莉莉|糖果

MongoDB频繁掉线频繁断开服务的核心原因以及解决方案-卓伊凡|贝贝|莉莉|糖果查看日志内容 &#xff1a;2025-07-22T17:05:20.2160800 I CONTROL [initandlisten] MongoDB starting : pid34231 port28018 dbpath/data/mongodb 64-bit hostVM-0-17-centos 2025-07-22T17:05:20.21…

VUE懒加载(4种方式)

第一种 使用 Webpack 的动态导入&#xff08;Dynamic Imports&#xff09;第二种 Vue Router 中的懒加载第三种 使用第三方库第四种 使用 Vuex 进行异步数据加载虽然不是直接的懒加载&#xff0c;但你可以在组件内部或 Vuex store 中使用异步 action 来加载数据&#xff0c;确保…

【ROS1】09-ROS通信机制——参数服务器

目录 一、参数服务器概念 二、参数操作 2.1 C实现 2.1.1 新增参数 2.1.2 修改参数 2.1.3 查询参数 2.1.4 删除参数 2.2 python实现 2.2.1 新增参数 2.2.2 修改参数 2.2.3 查询参数 2.2.4 删除参数 一、参数服务器概念 假设正在开发一个复杂的机器人应用&#xff0…

C#.NET dapper 详解

简介 Dapper 是由 Stack Overflow 团队开发的一个简单、高性能的微型 ORM&#xff08;Object‑Relational Mapper&#xff09;&#xff0c;仅几千行代码&#xff0c;依赖于 ADO.NET 的 IDbConnection&#xff0c;通过动态生成 IL 来映射结果到实体对象。 与 EF、NHibernate 这类…

【LeetCode 热题 100】35. 搜索插入位置——二分查找(左闭右开)

Problem: 35. 搜索插入位置 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 文章目录整体思路完整代码时空复杂度时间…

Python-初学openCV——图像预处理(四)——滤波器

目录 一、图像噪点消除噪声&#xff1a; 1、概念 2、均值滤波 3、方框滤波 4 、高斯滤波 5、中值滤波 6、双边滤波 7、总结 一、图像噪点消除噪声&#xff1a; 1、概念 指图像中的一些干扰因素&#xff0c;通常是由图像采集设备、传输信道等因素造成的&#xff0c;表现…

嵌入式系统可靠性设计

嵌入式系统可靠性设计硬件件可靠性设计1. 硬件设计原则2. 硬件设计注意问题2.1 引脚布局和走线2.2 元器件选择和布局2.3 电源和地线分离2.4 EMI/EMC设计2.5 系统可靠性2.6 资源利用和扩展性软件可靠性设计1. 设计原则1.1 模块化设计1.2 冗余设计1.3 容错设计1.4 实时性保障1.5 …