RabbitMQ 79b5ad38df29400fa52ef0085a14b02f

news2024/12/26 23:03:32

RabbitMQ

一、什么是消息队列


消息队列可以看作是一个存放消息的容器,其中,生产者负责生产数据到消息队列中,而消费者负责消费数据。消息队列是分布式系统中重要的组件,目前使用较多的消息队列有ActiveMQ,RabbitMQ,Kafka,RocketMQ。

消息队列主要解决了应用耦合、异步处理、流量削锋等问题。

二、Rabbit特点


RabbitMQ 是一款使用Erlang语言开发的,实现AMQP(高级消息队列协议)的开源消息中间件,它实现了高效、可靠、可扩展的消息传递机制。以下是 RabbitMQ 的一些主要特点:

  • 可靠性:RabbitMQ 提供了消息持久化、确认机制、事务等功能,确保消息传递的可靠性。
  • 灵活性:RabbitMQ 支持多种消息传递模式,例如点对点、发布/订阅、通配符等,可以根据不同的应用场景选择合适的模式。
  • 可扩展性:RabbitMQ 支持集群部署,可以通过添加节点来扩展消息处理能力。
  • 与多种编程语言兼容:RabbitMQ 提供了多种客户端库,可以与多种编程语言进行集成,例如 Java、Python、Go 等。
  • 丰富的功能:RabbitMQ 提供了多种功能,例如消息优先级、消息 TTL、延迟队列等,可以满足不同的业务需求。
  • 可视化管理界面:RabbitMQ 提供了一个可视化的管理界面,可以方便地管理队列、交换机、绑定关系等。

三、RabbitMQ的组成部分

  • Broker:消息队列服务进程。此进程包括两个部分:Exchange和Queue。
  • Exchange:消息队列交换机。按一定的规则将消息路由转发到某个队列
  • Queue:消息队列,存储消息的队列。
  • Producer:消息生产者。生产方客户端将消息同交换机路由发送到队列中。
  • Consumer:消息消费者。消费队列中存储的消息。

在这里插入图片描述

如图所示,RabbitMQ的工作流程分为以下几个部分

  • 消息生产者连接到RabbitMQ Broker,创建connection,开启channel。
  • 生产者声明交换机类型、名称、是否持久化等。
  • 生产者发送消息,并指定消息是否持久化等属性和routing key。
  • exchange收到消息之后,根据routing key路由到跟当前交换机绑定的相匹配的队列里面。
  • 消费者监听接收到消息之后开始业务处理。

四、RabbitMQ中Exchange


在RabbitMQ中,消息发送方不是直接将消息发送到queue中,而是先发送给exchange,由exchange再发送给对应的队列。exchange的类型有:**direct, topic, headers , fanout 。**默认的exchange,名为"",是一个没有名字的direct类型的exchange。发送到它的消息是基于路由键(routing key)路由到队列的。

4.1 Direct

direct,需要将一个队列绑定到交换机上,要求该消息与一个特定的routing key完全匹配。这是一个完整的匹配。如果一个队列绑定到该交换机上要求routing key为 “green”,则只有routing key为“green”的消息才被转发,不会转发routing key为"red",只会转发routing key为"green”

4.2 Topic

可以理解为通配符匹配,将routing key和某模式进行匹配。此时队列需要绑定要一个模式上。符号“#”匹配0个或多个词,符号“*”只能匹配一个词。

在这里插入图片描述

4.3 Fanout

Fanout 不需要指定routing key。你只需要简单的将队列绑定到交换机上。一个发送到该类型交换机的消息都会被广播到与该交换机绑定的所有队列上。
在这里插入图片描述

1.rabbitMQ的消息持久化的做法不是每接受一条消息就立即调用fsync,而是对接收到的消息进行缓存,接着再批量进行持久化。

3.rabbitMQ中的**AnonymousQueue** 默认是非持久化、自动删除的队列。

当消费者连接断开时,AnonymousQueue会被自动删除,队列中的消息也会被删除,不会持久化。

4.4 Headers

不处理routing key,而是根据发送的消息内容中的headers属性进行匹配。在绑定Queue与Exchange时指定一组键值对;当消息发送到RabbitMQ时会取到该消息的headers与Exchange绑定时指定的键值对进行匹配;如果完全匹配则消息会路由到该队列,否则不会路由到该队列。headers属性是一个键值对,可以是Hashtable,键值对的值可以是任何类型。而fanout,direct,topic 的路由键都需要要字符串形式的

在这里插入图片描述

RabbitMQ入门实战

首先在application.yml中配置RabbitMQ信息

spring:
    rabbitmq:
        host: 127.0.0.1
        port: 5672
        username: guest
        password: guest

接着添加配置类,在配置类中实现相关bean的注入

@Configuration
public class DirectRabbitConfig {

    @Bean
    public Queue rabbitmqDemoDirectQueue() {

        return new AnonymousQueue();
        /**
         *   等价于  return new Queue("direct_demo",false,false,false);
         * 1、name:    队列名称
         * 2、durable: 是否持久化
         * 3、exclusive: 是否独享、排外的。如果设置为true,定义为排他队列。则只有创建者可以使用此队列。也就是private私有的。
         * 4、autoDelete: 是否自动删除。也就是临时队列。当最后一个消费者断开连接后,会自动删除。
         * */
    }

    @Bean
    public DirectExchange rabbitmqDemoDirectExchange() {
        //Direct交换机
        return new DirectExchange("demo_exchange", true, false);
    }

    @Bean
    public Binding bindDirect() {
        //链式写法,将队列和交换机进行绑定,并设置匹配键
        return BindingBuilder
                //绑定队列
                .bind(rabbitmqDemoDirectQueue())
                //到交换机
                .to(rabbitmqDemoDirectExchange())
                //并设置匹配键
                .with("demo");
    }

		@Bean
    public Sender sender() {
				//生产者类
        return new Sender();
    }
		
		@Bean
    public Receiver receiver() {
				//消费者类
        return new Receiver();
    }
}

接下来,创建发送消息的Sender类和消费消息的Receiver类

/**
 * 生产者类
 */
public class Sender {

    @Autowired
    private RabbitTemplate template;

    @Autowired
    private DirectExchange direct;

		private final String MESSAGE = "Hello world";
		
		private final String key = "demo";

    @Scheduled(fixedDelay = 1000, initialDelay = 500)
    public void send() {
        template.convertAndSend(direct.getName(), key, MESSAGE);
        System.out.println("sending message: " + MESSAGE);
    }

}
/**
 * 消费者类
 */
@RabbitListener(queues = "#{rabbitmqDemoDirectQueue.name}")
public class Receiver {

    @RabbitHandler
    public void receive(String msg) {
        System.out.println("receive message: " + msg);
    }
}

最后,创建启动类,并加上@EnableScheduling 注解

@SpringBootApplication
@EnableScheduling
public class RabbitDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(RabbitAmqpTutorialsApplication.class, args);
    }
}

打开http://localhost:15672,可以看到RabbitMQ消息发送情况等信息

在这里插入图片描述

五、RabbitMQ的一些机制

5.1 消息应答

一般情况下,RabbitMQ中的broker向消费者发送一条消息后,便立即将该消息标记为删除。由于消费者处理一个消息可能需要一段时间,假如在处理消息中途消费者挂掉了,我们会丢失其正在处理的消息以及后续发送给该消费这的消息。为了保证消费者消费的可靠性,RabbitMQ 引入消息应答机制,即:**消费者在接收消息并且处理完该消息之后,才告知 RabbitMQ 可以把该消息删除了。**RabbitMQ 中消息应答方式有两种:自动应答(默认)、手动应答。

  • 自动应答

自动应答是RabbitMQ默认采用的消息应答方式,是指broker不在乎消费者对消息处理是否成功,都会告诉队列删除消息。如果处理消息失败,又没有捕获异常,则会实现自动补偿(队列重新向消费者投递消息);如果捕获异常了,broker以为消息消费成功,就会将消息从队列中删除,导致数据丢失。

  • 手动应答

手动应答,是指消费者处理完业务逻辑之后,手动返回ack(通知)告诉broker消息处理完了,你可以删除消息了;或者手动返回nack消息,告诉broker消息处理失败,别删除消息。如果消费者挂了而没有发送ACK或NACK,那么RabbitMQ会认为该消息未被处理,会将该消息重新分发给其他消费者,直到有一个消费者成功处理并发送ACK或NACK为止。这个过程被称为消息的重新入队列。在重新入队列的过程中,RabbitMQ会在消息的属性中增加一个计数器,表示该消息被重新分发的次数。如果该计数器的值超过了一个预定的阈值,那么RabbitMQ可能会将该消息标记为“死信”,并将其发送到一个指定的死信交换机(dead letter exchange)中。这个机制可以避免消息在系统中无限制地被重新分发,从而引起系统性能问题。

在springboot的application.yml中可以设置RabbitMQ的应答机制

spring:
  rabbitmq:
    listener:
      simple:
        acknowledge-mode: manual

消费者

@RabbitListener(queues = "#{Queue1.name}")
    public void onMessage1(Message message, Channel channel) throws Exception {
        try {
            MessageProperties messageProperties = message.getMessageProperties();
            byte[] body = message.getBody();
            String content = new String(body, 0, body.length, messageProperties.getContentEncoding());
            System.out.println("receiver1: " + content);
            channel.basicAck(messageProperties.getDeliveryTag(), true);
        } catch (Exception e) {
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }
    }

5.2 持久化

默认情况下 RabbitMQ 退出或由于某种原因崩溃时,它会清空队列和消息,除非告知它不要这样做。确保消息不会丢失需要做两件事:我们需要将队列和消息都标记为持久化

  • 队列持久化

  • 在这里插入图片描述

  • 消息持久化(在Spring Boot中使用RabbitTemplate发送消息时,默认情况下消息是持久化的)

@Autowired
private RabbitTemplate rabbitTemplate;

public void sendMessage(String message) {
    MessageProperties properties = new MessageProperties();
    properties.setDeliveryMode(MessageDeliveryMode.PERSISTENT); // 设置消息的持久化属性
    Message rabbitMessage = new Message(message.getBytes(), properties);
    rabbitTemplate.convertAndSend("exchangeName", "routingKey", rabbitMessage);
}

5.3 不公平分发

RabbitMQ 默认分发消息采用的轮询分发模式,但是在某种场景下这种策略并不是很好,比方说有两个消费者在处理任务,其中 consumer01 处理任务的速度非常快,而 consumer02 处理速度却很慢,此时如果我们还是采用轮询分发,就会使处理速度快的 consumer01 很大一部分时间处于空闲状态,而 consumer02 一直在干活。

可以通过设置channel的prefetchCount 为1,来实现不公平分发。该参数表示,该消费者当前只能处理一个消息。

channel.basicQos(1);

或者application.yml中设置

spring.rabbitmq.listener.simple.acknowledge-mode=manual      
spring.rabbitmq.listener.simple.prefetch=1

5.4 预取值

该值定义channel上允许的未确认消息的最大数量。一旦数量达到配置的数量,RabbitMQ 将停止在channel上传递更多消息,除非至少有一个未处理的消息被确认。假设在channel上有未确认的消息 5、6、7,8,并且channel的预取计数设置为 4,此时 RabbitMQ 将不会在该channel上再传递任何消息,除非至少有一个未应答的消息被 ack。比方说 tag=6 的消息刚刚被确认 ACK,RabbitMQ 将会感知这个情况到并再发送一条消息。对于自动确认机制,其预取值可以看做是无限。

5.5 发布确认

生产者将channel设置成 confirm 模式,一旦channel进入 confirm 模式,所有在该channel上面发布的消息都将会被指派一个唯一的 ID(从 1 开始),一旦消息被投递到所有匹配的队列之后,broker 就会发送一个确认给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了。

confirm 模式最大的好处在于他是异步的,一旦发布一条消息,生产者应用程序就可以在等channel返回确认的同时继续发送下一条消息,当消息最终得到确认之后,生产者应用便可以通过回调方法来处理该确认消息,如果 RabbitMQ 因为自身内部错误导致消息丢失,就会发送一条 nack 消息,生产者应用程序同样可以在回调方法中处理该 nack 消息。

发布确认机制有三种策略:单个确认发布批量确认发布异步确认发布

  • 单个确认发布

是一种同步确认发布的方式,也就是发布一个消息之后只有它被确认发布,后续的消息才能继续发布

  • 批量确认发布

与单个等待确认消息相比,先发布一批消息然后一起确认可以极大地提高吞吐量,当然这种方式的缺点就是:当发生故障导致发布出现问题时,不知道是哪个消息出现问题了,我们必须将整个批处理保存在内存中,以记录重要的信息而后重新发布消息。当然这种方案仍然是同步的,也一样阻塞消息的发布。

  • 异步确认发布

异步确认虽然编程逻辑比上两个要复杂,但是性价比最高,无论是可靠性还是效率都没得说,他是利用回调函数来达到消息可靠性传递的,这个中间件也是通过函数回调来保证是否投递成功,

要开启发布确认,需要配置application.yml

spring:
  #项目名称
  application:
    name: rabbitmq-provider
  #配置rabbitMq 服务器
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: rabbitMQ
    password: rabbitMQ
    #确认消息已发送到交换机(Exchange)
#    publisher-confirm-type: SIMPLE
    publisher-confirm-type: CORRELATED
    #确认消息已发送到队列(Queue)
    publisher-returns: true

然后,在rabbitTemplate中进行设置

@Slf4j
@Configuration
public class RabbitConfig {

    @Bean
    public RabbitTemplate createRabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate();
        rabbitTemplate.setConnectionFactory(connectionFactory);
       // Mandatory为true时,消息通过交换器无法匹配到队列会返回给生产者,为false时匹配不到会直接被丢弃
        rabbitTemplate.setMandatory(true);

        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            /**
             *  ConfirmCallback机制只确认消息是否到达exchange(交换器),不保证消息可以路由到正确的queue;
             *  需要设置:publisher-confirm-type: CORRELATED;
             *  springboot版本较低 参数设置改成:publisher-confirms: true
             *
             *  以实现方法confirm中ack属性为标准,true到达
             *  config : 需要开启rabbitmq得ack publisher-confirm-type
             */
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                log.info("ConfirmCallback  确认结果 (true代表发送成功) : {}  消息唯一标识 : {} 失败原因 :{}",ack,correlationData,cause);
            }
        });

        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            /**
             *  ReturnsCallback 消息机制用于处理一个不可路由的消息。在某些情况下,如果我们在发送消息的时候,当前的 exchange 不存在或者指定路由 key 路由不到,这个时候我们需要监听这种不可达的消息
             *   就需要这种return机制
             *
             *  config : 需要开启rabbitmq发送失败回退; publisher-returns 或rabbitTemplate.setMandatory(true); 设置为true
             */
            @Override
            public void returnedMessage(ReturnedMessage returned) {
//                实现接口ReturnCallback,重写 returnedMessage() 方法,
//                方法有五个参数
//                message(消息体)、
//                replyCode(响应code)、
//                replyText(响应内容)、
//                exchange(交换机)、
//                routingKey(队列)。

                log.info("ReturnsCallback    returned : {}",returned);
            }
        });

        return rabbitTemplate;
    }

}

5.6 死信队列

死信就是无法被消费的消息。一般来说,producer 将消息投递到 broker 或者直接到 queue 中,consumer 从 queue 取出消息进行消费,但某些时候由于特定的原因导致 queue 中的某些消息无法被消费,这样的消息如果没有后续的处理,就变成了死信,有死信自然就有了死信队列。

死信产生的原因:

  • 消息 TTL 过期
  • 队列达到最大长度(队列满了无法再添加数据到 mq 中)
  • 消息被拒绝(basic.reject 或 basic.nack)并且 requeue=false

5.7 延迟队列

延时队列,队列内部是有序的,最重要的特性就体现在它的延时属性上,延时队列中的元素是希望在指定时间到了以后或之前取出和处理,简单来说,延时队列就是用来存放需要在指定时间被处理的元素的队列。

RabbitMQ 中的 TTL

TTL 是 RabbitMQ 中一个消息或者队列的属性,表明一条消息或者该队列中的所有消息的最大存活时间,单位是毫秒。一条消息如果在TTL 设置的时间内没有被消费,则会成为"死信"。如果同时配置了队列的TTL 和消息的TTL,那么较小的那个值将会被使用。

实现延迟队列的两种方式:

  • 通过设置队列TTL+死信实现消息延迟

代码架构图如下所示,其中有两个direct类型的交换机XY,其中Y为死信交换机;还有三个队列QAQBQD,QA和QB为普通队列,其中QA中消息的ttl为10s,QB中消息的ttl为40s,QD为死信队列。队列与交换机之间的routing-key如图中连线上标注所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bbRRw2rv-1691716049857)(RabbitMQ%2079b5ad38df29400fa52ef0085a14b02f/Untitled%208.png)]

  • 通过设置消息TTL+死信实现消息延迟

以上延时队列的实现目前只有 10S 和 40S 两个时间选项,如果需要一个小时后处理,那么就需要增加TTL为一个小时的队列,如果是预定会议室然后提前通知这样的场景,岂不是要增加无数个队列才能满足需求?

因此我们需要做出一些优化,在这里新增了一个队列 QC,绑定关系如下,该队列不设置 TTL 时间,我们通过指定消息的 TTL 来实现消息的延迟

在这里插入图片描述

  • 下载延迟队列插件

参见:https://blog.csdn.net/qq_45173404/article/details/121687489

5.9 幂等性

所谓幂等性就是指用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。比如用户购买商品后支付后已经扣款成功,但是返回结果时出现网络异常,用户并不知道自己已经付费成功,于是再次点击按钮,此时就进行了第二次扣款,这次的返回结果成功。但是扣了两次用户的钱,这就出现了不满足幂等性,即用户对统一操作发起了一次或多次请求

对应消息队列 MQ 中出现的幂等性问题就是消息重复消费。比如消费者在消费 MQ 中的消息时,MQ 已把消息发送给消费者,消费者在给 MQ 返回 ack 时网络中断,故 MQ 未收到确认信息,该条消息会重新发给其他的消费者,或者在网络重连后再次发送给该消费者,但实际上该消费者已成功消费了该条消息,造成消费者的重复消费。

幂等性解决方案:https://zhuanlan.zhihu.com/p/176944177

5.10 优先级队列

在RabbitMQ中,队列需要设置为优先级队列的同时消息也必须设置消息的优先级才能生效,而且消费者需要等待消息全部发送到队列中才去消费因为这样才有机会对消息进行排序。

代码实现队列优先级

在这里插入图片描述

5.11 惰性队列

当生产者发送消息的速度超过了消费者处理消息的速度,就会导致队列中的消息堆积,直到队列存储消息达到上限。之后发送的消息就会成为死信,可能会被丢弃,这就是消息堆积问题。

从RabbitMQ的3.6.0版本开始,就增加了Lazy Queues的概念,也就是惰性队列。惰性队列的特征如下:

  • 接收到消息后直接存入磁盘而非内存
  • 消费者要消费消息时才会从磁盘中读取并加载到内存
  • 支持数百万条的消息存储

代码实现惰性队列
在这里插入图片描述

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

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

相关文章

unity实现角色体力功能【体力条+体力计算】

导读:实现功能 1、角色体力计算 2、角色疲劳动画 3、体力条制作、跟随 默认做好角色的idle/run/walk动画、切换和玩家输入,我使用的是新输入系统,动画时单变量混合树,参数Sports。 【每一部分功能根据自己需求观看哦】 1、角色体…

wsl2安装docker引擎(Install Docker Engine on Debian)

安装 1.卸载旧版本 在安装 Docker 引擎之前,您必须首先确保卸载任何冲突的软件包。 发行版维护者在他们的存储库。必须先卸载这些软件包,然后才能安装 Docker 引擎的正式版本。 要卸载的非官方软件包是: docker.iodocker-composedocker-…

使用gewe框架进行微信群组管理(一)

友情链接:geweapi.com 点击访问即可。 管理员操作 小提示: 添加、删除、转让多个wxid时仅限于添加/删除管理员,1添加 2删除 3转让 请求URL: http://域名地址/api/group/admin 请求方式: POST 请求头&#xff1a…

基本动态规划问题的扩展

基本动态规划问题的扩展 应用动态规划可以有效的解决许多问题,其中有许多问题的数学模型,尤其对一些自从57年就开始研究的基本问题所应用的数学模型,都十分精巧。有关这些问题的解法,我们甚至可以视为标准——也就是最优的解法。…

【LeetCode】870 . 优势洗牌

870 . 优势洗牌 方法:贪心 思路 这道题的思想类似于 “田忌赛马” ,把 nums1 当成是田忌的马,nums2 当成是齐威王的马。 讨论田忌的下等马(nums1 的最小值): 如果它能比过齐威王的下等马(nums…

PHP利用PCRE回溯次数限制绕过某些安全限制实战案例

目录 一、正则表达式概述 有限状态自动机 匹配输入的过程分别是: DFA(确定性有限状态自动机) NFA(非确定性有限状态自动机) 二、回溯的过程 三、 PHP 的 pcre.backtrack_limit 限制利用 例题一 回溯绕过步骤 &…

host文件被锁死无法修改怎么办?解锁host文件修改新方法~~

日常操作发现host文件被锁死,host文件左下角出现一个🔒,无法修改怎么办?别急,最简单的解决方法分享啦,一起来围观吧! 应用程序-实用工具中打开终端 输入代码【sudo chflags -hv noschg /etc/hos…

2023年游戏买量能怎么玩?

疫情过后,一地鸡毛。游戏行业的日子也不好过。来看看移动游戏收入:2022年,移动游戏收入达到920亿美元,同比下降6.4%。这告诉我们,2022年对移动游戏市场来说是一个小挫折。 但不管是下挫还是上升,移动游戏市…

软件测试面试夺命连环十七问,你答得上来么?这都不会建议多学!

1. 给你一个网站,该如何测试?(探究需求制订计划) 首先,查找需求说明、网站设计等相关文档,分析测试需求。 制定测试计划,确定测试范围和测试策略,一般包括以下几个部分&#xff1a…

【Spring MVC】Spring MVC基于注解的程序开发

目录 一、什么是Spring MVC 二、Spring MVC项目的创建和使用 1、实现客户端和服务器端之间的连接 1.1、RequsestMapping注解 1.2、RequestMapper的简单使用 1.3、使用GetMapping和POSTMapping注解来实现HTTP连接 三、获取参数 1、实现获取单个参数 2、实现获取对象 3…

002-Spring boot 自动配置相关分析

目录 自动配置开启自动配置读取配置提前过滤 自动配置 开启自动配置 在Spring 启动类上的 SpringBootApplication 中有 EnableAutoConfiguration 读取配置 Import(AutoConfigurationImportSelector.class) public interface EnableAutoConfiguration {AutoConfigurationEnt…

vxe table: 实现tree表格,并且自定义展示指定行

要求,数据中必须有唯一的id字段,并且row-config.KeyField 要指定这个id字段。否则在自定义展开行时展开不生效。并不影响tree的渲染 数据有两种形式 普通数据结构tree 状结构, 以树状结构为例: 首先我们要将普通结构的数据,按…

Go语言工程实践之测试与Gin项目实践

Go 语言并发编程 及 进阶与依赖管理_软工菜鸡的博客-CSDN博客 03 测试 回归测试一般是QA(质量保证)同学手动通过终端回归一些固定的主流程场景 集成测试是对系统功能维度做测试验证,通过服务暴露的某个接口,进行自动化测试 而单元测试开发阶段,开发者对单独的函数…

企业级帮助中心编写方案怎么写?

在现代商业环境中,为客户提供高效的支持和解决方案至关重要。企业级帮助中心是一个集中管理和呈现常见问题和解答的平台,可以为客户提供快速、便捷的自助帮助。本文将提供一个企业级帮助中心编写方案,旨在帮助企业提供优质的客户支持&#xf…

进程间通信(IPC)的几种方式

进程间通信(IPC) 1.常见的通信方式2.低级IPC方法文件 3.常用于本机的IPC机制3.1无名管道pipe3.2命名管道FIFO3.3消息队列MessageQueue3.4共享内存SharedMemory3.5信号量Semaphore3.6信号Signal3.7unix域套接字 4.不同计算机上的IPC机制5.IPC机制的数据拷…

数学符号说明——三角等号(≜)

三角等号 ,LaTex语法宏 (\triangleq),Unicode(U225C),又称 "delta equal to(Δ 等)"。可以读作 "等于"、"根据定义 x 等于 y "。 有时候,用在数学(和物理学)的某种定义中。例如&#…

VMware vCenter忘记密码操作,和Linus原理一致

mount -o remount,rw / passwd root ## 修改 root 密码要选择对应账户## 输入新密码,再输入一次新密码 umount / ## 卸载根文件系统 reboot -f ## 重新引导 vCenter

生信豆芽菜-t-test差异分析使用说明

网站&#xff1a;http://www.sxdyc.com/diffTtestAnalyse 一、t-test简介 t检验&#xff0c;亦称student t检验&#xff08;Student’s t test&#xff09;&#xff0c;主要用于样本含量较小&#xff08;例如n < 30&#xff09;&#xff0c;总体标准差σ未知的正态分布。 t检…

导入示例工程出现error: failed to start ability. Error while Launching activity错误的解决办法

导入华为健康生活应用&#xff08;ArkTS&#xff09;&#xff0c;使用DevEco Studio打开&#xff0c;运行报错&#xff1a; error: failed to start ability. Error while Launching activity解决办法&#xff1a;修改module.json5里面exported的值&#xff0c;由false改为tr…