RabbitMQ 笔记一

news2024/11/16 5:39:59

概览

MQ基本概念

RabbitMQ入门

基本工作模

1.MQ是什么?

MQ:Message Queue, 存储消息的中间件,是消息发送过程中的暂存容器,主要用于解决分布式系统进程间的通信。

分布式系统通信的两种方式:直接远程调用、借助第三方间接通信

为什么要使用消息中间件?

如有一个电商交易的场景,用户下单之后调用库存系统减库存,然后调用物流系统进行发货,如果刚开始交易,库存,物流都是属于一个系统,那么他们之间就是接口调用。但是随着系统的发展,各个模块业务越来越庞大、业务逻辑越来越复杂,这个时候就必然要做服务化和业务拆分。这个时候就需要考虑这些系统之间是如何交互的。首先想到的就是RPC(Remote Procedure Call),但是随着系统的发展,可能一笔交易后序需要调用几十个接口位于不同系统的接口,比如短信服务、邮件服务等等,这个时候就需要消息中间件来解决问题了。消息中间件最突出的特点就是提供数据传输的可靠性和高效性,主要解决分布式的系统数据传输需求

摘自:为什么使用消息中间件_为什么用消息中间件-CSDN博客

使用MQ的优势:

(1)应用解耦:提高系统容错性和可维护性

        整个系统耦合,会导致系统容错性低、可扩展性低、可维护性低。解耦之后,一个系统挂了,其它系统不会有问题。容错性高、可扩展性高、可维护性高。

(2)异步提速:提升用户体验和系统吞吐量.

        如果一个订单系统同步执行:则有: 订单进数据库20ms+调用子系统一300ms+调用子系统二300ms+调用子系统三300ms=920ms,用户等待920ms

        如果采用异步模式:则有 订单进数据库20ms+消息发到MQ5ms=25ms,用户等待25ms

(3)削峰填谷:提高系统稳定性

        请求瞬间增多每秒5000个,但是子系统每秒只能处理1000请求。

        削峰指的是:提高子系统的稳定性。加入中间件后,所有请求进入消息队列。帮子系统处理高并发的请求量。

        填谷指的是:大量的消息积压在MQ里。子系统每秒从MQ拉取1000个进行处理,直到处理完所有积压的消息。

使用MQ的劣势

(1)系统可用性降低

        引入的第三方插件|依赖越多,系统稳定性越差。

        如果MQ宕机,业务功能就会收到影响。需要额外的工作来确保MQ高可用性。

(2)系统复杂性提高

        没有MQ时:系统间同步远程调用

        引入MQ时:通过MQ异步调用

        引发的问题:如何保证消息不被重复消费?如何处理消息丢失?如何保证消息传递的顺序性。

(3)一致性问题

        消息:A——>MQ——>B|C|D

        如果BC处理成功,D失败了,如何保证数据一致性。

使用MQ应满足什么条件?

  1. 生产者不需要消费者的反馈。(消费者消费消息后返回值为空,这才能使异步调用成为可能)
  2. 容许短暂的不一致
  3. 用了有效果:解耦、提速、削峰等,超过引入MQ的管理成本

常见的MQ产品

2.RabbitMQ概述

RabbitMQ简介:

2007年,Rabbit技术公司 基于AMQP标准开发 Rabbit MQ1.0

使用Erlang语言(一种专门为高并发、分布式系统开发的语言|电信领域使用广泛)

AMQP协议

  1. Advanced Message Queuing Protocol高级消息队列协议
  2. 网络协议,应用层协议的一个开放标准,为面向消息的中间件设计。
  3. 2006年,AMQP规范发布(类比HTTP)
  4. 基于此协议的客户端与消息中间件之间传递消息,不受客户端/中间件产品、开发语言等限制。

RabbitMQ的组成:

Broker中间件,用于接收发信息的用用,如:RabbitMQ Server
Virtual host

虚拟机,处于多租户和安全因素设计的,把AMQP基本组件划分到一个虚拟的分组中,类似于网络中的namespace 。

应用场景:用户隔离

        多个不同用户使用同一个RabbitMQ时,可以划分出多个vhost,每个用户在自己的vhost创建exchange/queue等。

Connection链接,publisher/consumer和broker之间建立TCP链接。
Channel

connection内部的逻辑链接。作为一个轻量级Connection,极大减少了操作系统建立TCP链接的开销。

存在原因:        

        如果每次访问MQ都建立链接,消息量大的时候建立TCP链接,开销非常大,效率也低。

        所以使用channel内部逻辑链接,如果应用支持多线程,通常每个thread独占一个channel通信。

AMQP method中

        包含channel id帮助客户端和message broker识别channel

        所以channel之间是完全隔离的

Exchange

交换机,message到达broker的第一站,根据分发规则,匹配查询表中的routing key, 分发消息到queue。

常见的类型

        direct:        point to point

        topic:         publisher-subscribe

        fanout:       multicast

Queue消息队列,消息最终被送到这里等待被消费。
Binding

绑定,exchange 和 queue之间的虚拟连接,binding中包含routing key.

Binding信息被保存在exchange的查询表中,是message分发的依据。

RabbitMQ的工作模式:

        6种,包含:简单模式、work queues、Publish/Subscribe 发布与订阅模式、Routing 路由模式、Topics主题模式、RPC远程调用模式。

RabbitMQ官网:RabbitMQ Tutorials — RabbitMQ

补充:

        JMS:java消息服务(Java Message Service)应用程序接口,是java平台关于面向消息的中间件API

        JMS是Java EE 规范的一种,类比JDBC.

        很多消息中间件都实现了JMS规范,如:ActiveMQ。RabbitMQ没有提供JMS的实现,但开源社区有。

3.RabbitMQ的简单实现

RabbitMQ的安装:

1.安装RabbitMQ软件:

windows环境下安装RabbitMQ(超详细)_windows安装rabbitmq-CSDN博客

java依赖:

<dependency>
  <groupId>com.rabbitmq</groupId>
  <artifactId>amqp-client</artifactId>
  <version>5.20.0</version>
</dependency>

2.开启管理界面及配置:

  • 默认端口号:5672
  • 图形化界面地址: http://127.0.0.1:15672
  • 登陆名: guest    密码:guest   
  • 配置文件:

3.启动服务及基础配置:

RabbitMQ简单模式:

RabbitMQ生产者:

package org.example.producer;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class SimpleProducer {
    public void publishMessage() throws IOException, TimeoutException {
        //1.创建连接工厂
        ConnectionFactory factory=new ConnectionFactory();
        //2.设置参数
        factory.setHost("127.0.0.1");//ip 默认值localhost
        factory.setPort(5672);//端口 默认值5672
        factory.setVirtualHost("/itcast");//虚拟机 默认值/
        factory.setUsername("heima");
        factory.setPassword("heima");
        //3.创建链接 Connection
        Connection connection=factory.newConnection();
        //4.创建Channel
        Channel channel=connection.createChannel();
        //5.创建队列Queue
        /*
        queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
         queue: 队列名称
         durable: 是否持久化,是的话,mq重启后,数据还在。
         exclusive:
            是否独占,只能有一个消费者监听队列
            当connection关闭时,是否删除队列
          autoDelete: 是否自动删除,当没有consumer时,自动删除。
          arguments: 参数
         */
        channel.queueDeclare("hello_world",true,false,false,null);
        //6.发送消息
        /*
        basicPublish(String exchange, String routingKey, AMQP.BasicProperties props, byte[] body) t
        exchange:交换机名称,简单模式下交换机会使用默认的“”
        routingKey: 路由名称
        props: 配置消息
        body:  发送消息数据
         */
        String body="hello rabbitMQ!";
        channel.basicPublish("","hello_world",null,body.getBytes());
        //7.释放资源
        channel.close();
        connection.close();
    }
}

生产者生产一个消息:

RabbitMQ消费者:

package org.example.consumer;



import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class SimpleConsumer {

    public static void main(String[] args) throws IOException, TimeoutException {
        SimpleConsumer producer=new SimpleConsumer();
        producer.consumerMessage();
    }
    public void consumerMessage() throws IOException, TimeoutException {
        //1.创建连接工厂
        ConnectionFactory factory=new ConnectionFactory();
        //2.设置参数
        factory.setHost("127.0.0.1");//ip 默认值localhost
        factory.setPort(5672);//端口 默认值5672
        factory.setVirtualHost("/");//虚拟机 默认值/
        factory.setUsername("guest");
        factory.setPassword("guest");
        //3.创建链接 Connection
        Connection connection=factory.newConnection();
        //4.创建Channel
        Channel channel=connection.createChannel();
        //5.创建队列Queue
        /*
        queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
         queue: 队列名称
         durable: 是否持久化,是的话,mq重启后,数据还在。
         exclusive:
            是否独占,只能有一个消费者监听队列
            当connection关闭时,是否删除队列
          autoDelete: 是否自动删除,当没有consumer时,自动删除。
          arguments: 参数
         */
        channel.queueDeclare("hello_world",true,false,false,null);
        //6.接收消息
        /*
        basicPublish(String exchange, String routingKey, AMQP.BasicProperties props, byte[] body) t
        exchange:交换机名称,简单模式下交换机会使用默认的“”
        routingKey: 路由名称
        props: 配置消息
        body:  发送消息数据
         */
        Consumer consumer = new DefaultConsumer(channel){
            /*
            此处重写该方法是为了打印回调结果
            回调方法,收到回调方法后,会自动执行该方法
            consumerTag: 标识
            envelope: 获取一些信息,交换机,路由key
            properties: 配置信息
            body: 数据
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("consumerTag:"+consumerTag);
                System.out.println("Exchange:"+envelope.getExchange());
                System.out.println("RoutingKey:"+envelope.getRoutingKey());
                System.out.println("properties:"+properties);
                System.out.println("body:"+new String(body));
            }

        };
        channel.basicConsume("hello_world",true,consumer);
        //7.不需要释放资源,因为要监听队列

    }
}

总结:

P:生产者,也就是要发送消息的程序。

C:   消费者,消息的接收者,监听队列等待消息到来。

Queue: 消息队列,类似邮箱,可以缓存消息,生产者向其中投递消息,消费者从中取出消息。

4.5种基本工作模式

(1)简单模式 Hello World:

一个生产者,一个队列,一个消费者,不需要设置交换机(使用默认交换机)

(2)工作队列模式Work Queue:

特点: 一个生产者,一个队列,多个消费者(竞争关系),不需要设置交换机(使用默认交换机),同一个消息,对消费者来说是竞争关系,只有一个消费者能消费。

应用场景:对于任务过重或任务较多的情况使用工作队列可以提高任务处理速度。

例如:短信服务部署多个,只需要有一个节点发送成功即可。

发送端:发布多条消息

//创建新的队列
        channel.queueDeclare("work_queues",true,false,false,null); 
//发多条消息
        String body="hello rabbitMQ!";
        for(int i=0;i<10;i++){
            channel.basicPublish("","hello_world",null,(i+"-----"+body).getBytes());
        }

接收端:多个消费者竞争消费

创建两个消费者consumer1和consumer2,先启动两个消费者,再启动生产者生产消息,观察到两个消费者的消费过程。

消费者需要修改的地方:监听新的队列

channel.basicConsume("work_queues",true,consumer);

consumer1:

consumer2:

(3)发布Publish/subscribe:

        需要设置类型为fanout的交换机,并且交换机和队列进行绑定,当消息发送到交换机后,交换机将消息发送到绑定队列。

订阅模式多了一个交换机概念Exchange,且过程略有变化:

P: 消息生产者,消息发送给交换机

C:消息的接收者,监听消息队列,等待消息到来

Queue: 消息队列,接收消息,缓存消息。

Exchange: 交换机,只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息会丢失。

发送端:引入交换机,并对交换机和队列进行绑定

创建交换机、两个队列、绑定交换机和队列;发送消息并释放资源

其中交换机类型:BuiltinExchangeType枚举

关键代码

//4.创建Channel
        Channel channel=connection.createChannel();

        //定义交换机
        /*
        exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments) throws IOException {
        exchange: 交换机名称
        type: 交换机类型
            DIRECT("direct"),:定向
            FANOUT("fanout"),:扇形(广播),发送消息到每一个消费者
            TOPIC("topic"),:通配符的方式
            HEADERS("headers");:参数匹配

        durable: 是否持久化
        autoDelete: 自动删除
        internal: 内部使用,一般false
        arguments: 参数
         */
        String exchangeName="test_fanout";
        channel.exchangeDeclare(exchangeName, BuiltinExchangeType.FANOUT,true,false,false,null);


        //5.创建队列Queue
        String queueName1="test_fanout_queue1";
        String queueName2="test_fanout_queue2";
        channel.queueDeclare(queueName1,true,false,false,null);
        channel.queueDeclare(queueName2,true,false,false,null);

        //绑定交换机
        /*
         queueBind(String queue, String exchange, String routingKey, Map<String, Object> arguments)
         queue:队列名称
         exchange:交换机名称
         routingKey:路由键,绑定规则
            如果交换机的类型为fanout,routingKey设置为“”
         arguments:参数
         */
        channel.queueBind(queueName1,exchangeName,"");
        channel.queueBind(queueName2,exchangeName,"");

        //6.发送消息
        String body="日志信息: 张三调用了FindAll方法...日志级别:info...";
        channel.basicPublish(exchangeName,"",null,body.getBytes());

        //7.释放资源
        channel.close();
        connection.close();

 接收端:创建两个消费者,分别监听两个队列

consumer1监听queue1,consumer2监听queue2

//Consumer1:
channel.basicConsume("test_fanout_queue1",true,consumer);

//Consumer2:
channel.basicConsume("test_fanout_queue2",true,consumer);

启动生产者,消息生产正常,启动消费者1,启动消费者2,两个消费者都收到了消息。

consumer1:

consumer2: 

(4)路由模式Routing:

        需要设置类型为direct的交换机,交换机和队列进行绑定,并且指定routing key, 当发送消息到交换机后,交换机会根据routing key 将消息发送到对应的队列。

队列与交换机的绑定,不能是任意绑定,而是根据routing key绑定队列,消息根据绑定来决定分发到哪个队列中。

发送端:交换机绑定队列时,指定路由模式

注意:交换者的类型为:BuiltinExchangeType.TOPIC

关键代码:

 //4.创建Channel
        Channel channel=connection.createChannel();
        String exchangeName="test_topic";
        channel.exchangeDeclare(exchangeName, BuiltinExchangeType.TOPIC,true,false,false,null);


        //5.创建队列Queue
        String queueName1="test_routing_queue1";
        String queueName2="test_routing_queue2";
        channel.queueDeclare(queueName1,true,false,false,null);
        channel.queueDeclare(queueName2,true,false,false,null);

        //绑定交换机
        /*
         queueBind(String queue, String exchange, String routingKey, Map<String, Object> arguments)
         queue:队列名称
         exchange:交换机名称
         routingKey:路由键,绑定规则
            如果交换机的类型为fanout,routingKey设置为“”
         arguments:参数
         */
        channel.queueBind(queueName1,exchangeName,"error");
        channel.queueBind(queueName2,exchangeName,"info");
        channel.queueBind(queueName2,exchangeName,"error");
        channel.queueBind(queueName2,exchangeName,"warning");

        //6.发送消息
        String body="日志信息: 张三调用了FindAll方法...日志级别:info...";
        channel.basicPublish(exchangeName,"info",null,("info:\t"+body).getBytes());
        channel.basicPublish(exchangeName,"error",null,("error:\t"+body).getBytes());
        channel.basicPublish(exchangeName,"warning",null,("warning:\t"+body).getBytes());

接收端:创建Consumer1类,Consumer2类。

consumer1 监听队列1, consumer2监听队列2

//consumer1 
channel.basicConsume("test_routing_queue1",true,consumer);


//consumer2
channel.basicConsume("test_routing_queue2",true,consumer);

启动生产者生产正常,启动消费者1,启动消费者2

consumer1:

consumer2:

(5)通配符模式Topic:

        需要设置类型为topic的交换机,交换机和队列进行绑定,并且指定通配符方式的routing key, 当发送消息到交换机后,交换机会根据routing key将消息发送到对应的队列。

应用场景:如像根据日志级别监听某个子系统 系统名.error 消息,并入库

发送者

指定路由方式,但是路由方式以通配符匹配的形式存在:  #匹配一个  *匹配多个

 channel.queueBind(queueName1,exchangeName,"#.error");
        channel.queueBind(queueName2,exchangeName,"order.*");
        channel.queueBind(queueName2,exchangeName,"*.*");

        //6.发送消息
        String body="日志信息: 张三调用了FindAll方法...日志级别:info...";
        channel.basicPublish(exchangeName,"order.info",null,("order.info:\t"+body).getBytes());
        channel.basicPublish(exchangeName,"order.error",null,("order.error:\t"+body).getBytes());
        channel.basicPublish(exchangeName,"A.error",null,("A.error:\t"+body).getBytes());
      

接收端:创建Consumer1类,Consumer2类。

consumer1监听队列1,consumer2监听队列2

//Consumer1
channel.basicConsume("test_topic_queue1",true,consumer);


//Consumer2
channel.basicConsume("test_topic_queue2",true,consumer);

consumer1:

consumer2:

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

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

相关文章

npm,cnpm install报:Error: certificate has expired at TLSSocket.onConnectSecure

问题描述 最近发现前端项目 CI/CD 时失败&#xff0c;报下面的错误。npm淘宝镜像源证书过期导致的。 [npminstall:get] retry GET https://registry.npm.taobao.org/vue-router after 400ms, retry left 1, error: ResponseError: certificate has expired, GET https://reg…

TS学习笔记十:装饰器及三斜线指令

本节介绍TS中的装饰器和三斜线指令&#xff0c; 装饰器&#xff08;Decorators&#xff09;为我们在类的声明及成员上通过元编程语法添加标注提供了一种方式。   三斜线指令是包含单个XML标签的单行注释。 注释的内容会做为编译器指令使用。 讲解视频 20240116-205052装饰器…

CQ 社区版 2.8.0 | 支持TiDB、StarRocks,新增列过滤算法、导出模式设置等

Hello&#xff0c;CloudQuery 社区版 2.8.0 已发布&#xff0c;本文将带大家详细解析本次更新的功能~&#xff08;完整的讲解视频可点击 &#x1f449;&#x1f3fb; CloudQuery 社区版2.8.0 功能讲解演示 本期亮点更新 新增支持数据源 TiDB、StarRocks数据保护新增列过滤脱敏…

【iOS ARKit】人脸检测追踪基础

在计算机人工智能&#xff08;Artificial Inteligence,AI&#xff09;物体检测识别领域&#xff0c;最先研究的是人脸检测识别&#xff0c;目前技术发展最成熟的也是人脸检测识别。人脸检测识别已经广泛应用于安防、机场、车站、闸机、人流控制、安全支付等众多社会领域&#x…

[C#]winform部署yolov7+CRNN实现车牌颜色识别车牌号检测识别

【官方框架地址】 https://github.com/WongKinYiu/yolov7.git 【框架介绍】 Yolov7是一种目标检测算法&#xff0c;全称You Only Look Once version 7。它是继Yolov3和Yolov4之后的又一重要成果&#xff0c;是目标检测领域的一个重要里程碑。 Yolov7在算法结构上继承了其前…

C#使用RabbitMQ-2_详解工作队列模式

简介 &#x1f340;RabbitMQ中的工作队列模式是指将任务分配给多个消费者并行处理。在工作队列模式中&#xff0c;生产者将任务发送到RabbitMQ交换器&#xff0c;然后交换器将任务路由到一个或多个队列。消费者从队列中获取任务并进行处理。处理完成后&#xff0c;消费者可以向…

当你的Kindle被冻结或锁定时怎么办?这里提供几个解决办法

这篇文章解释了如果你的Kindle被锁住了该怎么办,以及修复被锁住的Kindle的所有最常见的方法。如果你的Kindle已经通电,但没有响应,那么你可以使用这些方法来修复它。 你的Kindle是不是冻结了太长时间以至于电池没电了,现在却无法打开?你也可以修复一个无法打开的Kindle。…

利用Maven获取jar包

我有一个习惯&#xff0c;就是程序不在线依赖网络的任何包。以前用C#时候虽然用Nuget找包&#xff0c;但是添加引用后又马上把Nuget引用删了&#xff0c;再把Nuget下载的dll拷贝到工程再引用dll。 这样做的好处是&#xff1a; 1.别人得到程序代码可以直接编译&#xff0c;不用…

【寒假每日一题·2024】AcWing 4965. 三国游戏(补)

文章目录 一、题目1、原题链接2、题目描述 二、解题报告1、思路分析2、时间复杂度3、代码详解 一、题目 1、原题链接 4965. 三国游戏 2、题目描述 二、解题报告 1、思路分析 思路参考y总&#xff1a;y总讲解视频 &#xff08;1&#xff09;题目中的获胜情况分为三种&#xff…

SQL查询数据库环境(dm8达梦数据库)

SQL查询数据库环境dm8达梦数据库 环境介绍 环境介绍 某些环境没有图形化界面,可以使用sql语句查询达梦数据库环境情况 SELECT 实例名称 数据库选项,INSTANCE_NAME 数据库选项相关参数值 FROM V$INSTANCE UNION ALL SELECT 授权用户,(SELECT AUTHORIZED_CUSTOMER FROM V$LICE…

微软 Power Apps model drven app 模型驱动应用使用Plugin插件实现业务流程跳转阶段功能

微软 Power Apps model drven app 模型驱动应用使用Plugin插件实现业务流程跳转阶段功能 模型驱动应用使用插件实现跳转业务流程阶段跳转功能 在实际操作中总会遇到使用业务流程的需求&#xff0c;那么如何使用plugin实现跳转阶段的功能呢 需求背景是主表上有业务流程&#x…

vue 本地中导入 maptalks

1、进入 github 中 maptalks 文件下载页面&#xff08;https://github.com/maptalks/maptalks.js/releases&#xff09; 这里可能会有朋友应为网络问题打不开 github &#xff0c;可以查看作者另一篇关于解决该问题的文章&#x1f449;GitHub 打不开问题解决 2、将下载好的文件…

为什么时序逻辑电路会落后一拍?

1、时序逻辑电路落后一拍&#xff1f; FPGA初学者可能经常听到一句话&#xff1a;“时序逻辑电路&#xff0c;或者说用 < 输出的电路会延迟&#xff08;落后&#xff09;一个时钟周期。”但在仿真过程中经常会发现不符合这一“定律”的现象–明明是在仿真时序逻辑&#xff…

2024年AI全景预测

欢迎来到 2024 年人工智能和技术的可能性之旅。 在这里&#xff0c;每一个预测都是一个潜在的窗口&#xff0c;通向充满创新、变革、更重要的是类似于 1950 年代工业革命的未来。 20 世纪 50 年代见证了数字计算的兴起&#xff0c;重塑了行业和社会规范。 如今&#xff0c;人工…

VR全景如何引爆民宿热潮?

“尔滨”旅游热还未消散&#xff0c;好看的风景、好吃的美食统统安排起来&#xff0c;但是不知道大家出游对住的环境有没有讲究呢&#xff1f;很多人喜欢民宿的原因&#xff0c;就是因为游玩一整天&#xff0c;希望有一个温馨舒适的住处&#xff0c;来缓解身体、精神上的疲劳。…

中仕教育:事业单位考试考什么?

事业单位考试分为两个阶段&#xff0c;分别是笔试和面试&#xff0c;考试科目包括公共科目和专业科目两部分。 公共科目内容是公共基础知识、职业能力测试或申论。一种形式为&#xff1a;公共基础知识职业能力测试或职业能力测试申论。另一种形式为&#xff1a;公共基础申论。…

02-Redis持久化、主从与哨兵架构详解

文章目录 Redis持久化RDB快照&#xff08;snapshot&#xff09;bgsave的写时复制(COW)机制AOF&#xff08;append-only file&#xff09;AOF重写RDB 和 AOF &#xff0c;我应该用哪一个&#xff1f; Redis 4.0 混合持久化Redis数据备份策略&#xff1a; Redis主从架构redis主从…

Kerberos认证过程

Kerberos协议角色组成&#xff1a; Kerberos协议中存在三个角色&#xff0c;分别是&#xff1a; 客户端 (client)&#xff1a;发送请求的一方服务端&#xff08;server&#xff09;接受请求的一方钥匙分发中心(Key distribution KDC) 密钥分发中心又分为两个部分&#xff0…

Leetcode—30. 串联所有单词的子串【困难】

2023每日刷题&#xff08;九十五&#xff09; Leetcode—30. 串联所有单词的子串 实现代码 class Solution { public:vector<int> findSubstring(string s, vector<string>& words) {unordered_map<string, int> raw;// words单词个数int n words.siz…

勒索袭击新方式,提防注册机中注入的勒索病毒!

1 事件概述 近期&#xff0c;用户反馈称自己在使用某款“注册机”软件时候&#xff0c;系统中文件被不行加密。通过对受害用户提供的线索和样本进 行综合分析研判&#xff0c;发现了一款借助破解类工具进行传播的新型勒索软件&#xff0c;其会通过向桌面释放勒索信与收款码图片…