全网最详细地理解Kafka中的Topic和Partition以及关于kafka的消息分发、服务端如何消费指定分区、kafka的分区分配策略(range策略和RoundRobin策略)

这篇具有很好参考价值的文章主要介绍了全网最详细地理解Kafka中的Topic和Partition以及关于kafka的消息分发、服务端如何消费指定分区、kafka的分区分配策略(range策略和RoundRobin策略)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 文章引言

最近在学习kafka相关的知识,特将学习成功记录成文章,以供大家共同学习。

首先要注意的是,Kafka中的TopicActiveMQ中的Topic是不一样的。

Kafka中,Topic是一个存储消息的逻辑概念,可以认为是一个消息集合。每条消息发送到Kafka集群的消息都有一个类别。

物理上来说,不同的Topic的消息是分开存储的,每个Topic可以有多个生产者向它发送消息,也可以有多个消费者去消费其中的消息。

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

每个Topic可以划分多个分区**(每个Topic至少有一个分区)**,同一Topic 下的不同分区包含的消息是不同的。

每个消息在被添加到分区时,都会被分配一个offset,它是消息在此分区中的唯一编号,Kafka通过offset保证消息在分区内的顺序。

offset的顺序不跨分区,即Kafka只保证在同一个分区内的消息是有序的。

消息是每次追加到对应的Partition的后面:

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

2. Topic & Partition的存储

Topic是一个逻辑上的概念,具体的存储还是基于Partition来的。

创建一个test2 Topic(注意这里的 partitions 参数为 3)

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

可以进入/tmp/kafka-logs目录下进行查看(当前机器IP 192.168.220.135),如下图所示:

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

在另外一台136机器上:

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

可以发现:

  1. 135机器上有test2-0test2-2

  2. 136机器上有test2-1

接下来,再结合Kafka的消息分发策略来看。

3. Kafka的消息分发

Kafka中最基本的数据单元就是消息,而一条消息其实是由Key + Value组成:

  1. Key是可选项,可传空值

  2. Value也可以传空值

这也是与ActiveMQ不同的一个地方。

在发送一条消息时,我们可以指定这 Key,那 Producer会根据Keypartition机制来判断当前这条消息应该发送并存储到哪个partition 中(这个就跟分片机制类似)。

我们可以根据需要进行扩展Producerpartition机制 (默认算法是hash%

如下扩展自己的partition代码所示:

 
/**
 * 消息发送后会调用自定义的策略
 *
 * @author super先生
 * @date 2023/2/10 14:20
 */
public class MyPartitioner implements Partitioner {
 
    @Override
    public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
        //获取当前 topic 有多少个分区(分区列表)
        List<PartitionInfo> partitions = cluster.partitionsForTopic(topic);
        int partitionNum = 0;
        if (key == null) { //之前介绍过 Key 是可以传空值的
            partitionNum = new Random().nextInt(partitions.size());   //随机
        } else {
            //取 %
            partitionNum = Math.abs((key.hashCode()) % partitions.size());
        }
        System.out.println("key:" + key + ",value:" + value + ",partitionNum:" + partitionNum);
        //发送到指定分区
        return partitionNum;
    }
 
    @Override
    public void close() {}
 
    @Override
    public void configure(Map<String, ?> configs) {}
}

生产者和消费者代码可参考我的博文:实现kafka的生产者(Producer)和消费者(Consumer)的代码

如下创建kafka生产者(Producer)的代码:

/**
 * @author super先生
 * @date 2023/2/10 14:40
 */
public class KafkaProducerDemo extends Thread {
    /**
     * 消息发送者
     */
    private final KafkaProducer<Integer, String> producer;
 
    /**
     * topic
     */
    private final String topic;
 
    private final Boolean isAsync;
 
    public KafkaProducerDemo(String topic, Boolean isAsync) {
        this.isAsync = isAsync;
        //构建相关属性
        //@see ProducerConfig
        Properties properties = new Properties();
        //Kafka 地址
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.220.135:9092,192.168.220.136:9092");
        //kafka 客户端 Demo
        properties.put(ProducerConfig.CLIENT_ID_CONFIG, "KafkaProducerDemo");
        //The number of acknowledgments the producer requires the leader to have received before considering a request complete. This controls the durability of records that are sent.
        /**发送端消息确认模式:
         *  0:消息发送给broker后,不需要确认(性能较高,但是会出现数据丢失,而且风险最大,因为当 server 宕机时,数据将会丢失)
         *  1:只需要获得集群中的 leader节点的确认即可返回
         *  -1/all:需要 ISR 中的所有的 Replica进行确认(集群中的所有节点确认),最安全的,也有可能出现数据丢失(因为 ISR 可能会缩小到仅包含一个 Replica)
         */
        properties.put(ProducerConfig.ACKS_CONFIG, "-1");
 
        /**【调优】
         * batch.size 参数(默认 16kb)
         *  public static final String BATCH_SIZE_CONFIG = "batch.size";
         *
         *  producer对于同一个 分区 来说,会按照 batch.size 的大小进行统一收集进行批量发送,相当于消息并不会立即发送,而是会收集整理大小至 16kb.若将该值设为0,则不会进行批处理
         */
 
        /**【调优】
         * linger.ms 参数
         *  public static final String LINGER_MS_CONFIG = "linger.ms";
         *  一个毫秒值。Kafka 默认会把两次请求的时间间隔之内的消息进行搜集。相当于会有一个 delay 操作。比如定义的是1000(1s),消息一秒钟发送5条,那么这 5条消息不会立马发送,而是会有一个 delay操作进行聚合,
         *  delay以后再次批量发送到 broker。默认是 0,就是不延迟(同 TCP Nagle算法),那么 batch.size 也就不生效了
         */
        //linger.ms 参数和batch.size 参数只要满足其中一个都会发送
 
        /**【调优】
         * max.request.size 参数(默认是1M)   设置请求最大字节数
         * public static final String MAX_REQUEST_SIZE_CONFIG = "max.request.size";
         * 如果设置的过大,发送的性能会受到影响,同时写入接收的性能也会受到影响。
         */
 
        //设置 key的序列化,key 是 Integer类型,使用 IntegerSerializer
        //org.apache.kafka.common.serialization
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.IntegerSerializer");
        //设置 value 的序列化
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
 
        //指定分区策略
        properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG,"superJson.kafka.partition.MyPartitioner");
 
        //构建 kafka Producer,这里 key 是 Integer 类型,Value 是 String 类型
        producer = new KafkaProducer<Integer, String>(properties);
        this.topic = topic;
    }
 
    public static void main(String[] args) {
        new KafkaProducerDemo("test2",true).start();
    }
 
    @Override
    public void run() {
        int num = 0;
        while (num < 100) {
            String message = "message--->" + num;
            System.out.println("start to send message 【 " + message + " 】");
            if (isAsync) {  //如果是异步发送
                producer.send(new ProducerRecord<Integer, String>(topic, message), new Callback() {
                    @Override
                    public void onCompletion(RecordMetadata metadata, Exception exception) {
                        if (metadata!=null){
                            System.out.println("async-offset:"+metadata.offset()+"-> partition"+metadata.partition());
                        }
                    }
                });
            } else {   //同步发送
                try {
                    RecordMetadata metadata = producer.send(new ProducerRecord<Integer, String>(topic, message)).get();
                    System.out.println("sync-offset:"+metadata.offset()+"-> partition"+metadata.partition());
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
            }
            num++;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

实现kafka的消费者(Consumer)中在接收消息的时候输出分区,如下代码所示:

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

 
/**
 * @author super先生
 * @date 2023/2/10 15:10
 */
public class KafkaConsumerDemo extends Thread {
 
    private final KafkaConsumer<Integer, String> kafkaConsumer;
 
    public KafkaConsumerDemo(String topic) {
        //构建相关属性
        //@see ConsumerConfig
        Properties properties = new Properties();
        properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.220.135:9092,192.168.220.136:9092");
        //消费组
        /**
         * consumer group是kafka提供的可扩展且具有容错性的消费者机制。既然是
         一个组,那么组内必然可以有多个消费者或消费者实例((consumer instance),
         它们共享一个公共的ID,即group ID。组内的所有消费者协调在一起来消费订
         阅主题(subscribed topics)的所有分区(partition)。当然,每个分区只能由同一
         个消费组内的一个consumer来消费.后面会进一步介绍。
         */
        properties.put(ConsumerConfig.GROUP_ID_CONFIG, "KafkaConsumerDemo");
 
        /** auto.offset.reset 参数  从什么时候开始消费
         *  public static final String AUTO_OFFSET_RESET_CONFIG = "auto.offset.reset";
         *
         *  这个参数是针对新的groupid中的消费者而言的,当有新groupid的消费者来消费指定的topic时,对于该参数的配置,会有不同的语义
         *  auto.offset.reset=latest情况下,新的消费者将会从其他消费者最后消费的offset处开始消费topic下的消息
         *  auto.offset.reset= earliest情况下,新的消费者会从该topic最早的消息开始消费
            auto.offset.reset=none情况下,新的消费组加入以后,由于之前不存在 offset,则会直接抛出异常。说白了,新的消费组不要设置这个值
         */
 
        //enable.auto.commit
        //消费者消费消息以后自动提交,只有当消息提交以后,该消息才不会被再次接收到(如果没有 commit,消息可以重复消费,也没有 offset),还可以配合auto.commit.interval.ms控制自动提交的频率。
        //当然,我们也可以通过consumer.commitSync()的方式实现手动提交
        properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true");
 
        /**max.poll.records
         *此参数设置限制每次调用poll返回的消息数,这样可以更容易的预测每次poll间隔
         要处理的最大值。通过调整此值,可以减少poll间隔
         */
 
        //间隔时间
        properties.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");
        //反序列化 key
        properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.IntegerDeserializer");
        //反序列化 value
        properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
        //构建 KafkaConsumer
        kafkaConsumer = new KafkaConsumer<>(properties);
        //设置 topic
        kafkaConsumer.subscribe(Collections.singletonList(topic));
    }
 
 
    /**
     * 接收消息
      */
    @Override
    public void run() {
        while (true) {
            //拉取消息
            ConsumerRecords<Integer, String> consumerRecord = kafkaConsumer.poll(100000000);
            for (ConsumerRecord<Integer, String> record : consumerRecord) {
                //record.partition() 获取当前分区
                System.out.println(record.partition()+"】】  message receive 【" + record.value() + "】");
            }
        }
    }
 
    public static void main(String[] args) {
        new KafkaConsumerDemo("test2").start();
    }
 
}

首先启动Consumer,再启动Producer

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

可以看到是能够对的上的。

默认情况下,Kafka采用的是hash 取 % 的分区算法

如果Keynull,则会随机分配一个分区。

这个随机是在这个参数metadata.max.age.ms的时间范围内随机选择一个。

对于这个时间段内,如果Key为 null,则只会发送到唯一的分区。这个值默认情况下是 10 分钟更新一次 (因为 partition 状态可能会发生变化)

4. 关于 Metadata

Metadata包含 TopicPartitionbroker 的映射关系,每一个 Topic 的每一个 partition,需要知道对应的 broker 列表是什么,Leader 是谁,Follower 是谁。

这些信息都是存储在Metadata这个类中,如下图所示:

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

5. 消费端如何消费指定分区

Consumer可以指定具体消费的分区,如下图所示:

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

再重新启动ConsumerProducer

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

可以看到Consumer只消费了分区为1的消息。

以上是单个Consumer消费(指定)分区的情况。

一般每个Topic都会有多个partition(主要是用于数据分片,减少消息的容量,从而提升 I/O 性能)。

当然也可以使用多个Consumer从而提高消费能力,有一个消费组的概念(具体可参看:一文了解kafka消息队列)

如果Consumer1、Consumer2 和 Consumer3 都属于group.id 为1 的消费组,那么消费情况如下:

  1. Consumer1就会消费 p0

  2. Consumer2就会消费p1

  3. Consumer3就会消费p2

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

不使用指定分区的方式创建三个Consumer

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

而且,它们都是同一个消费组:

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发
同时启动三个ConsumerProducer,而且它们都是同一个消费组:

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

可以看到三个Consumer分别消费三个Partition,很均匀。

对同一个Group来说,其中的Consumer可以消费指定分区也可以消费自动分配的分区(这里是 Consumer数量和partition数量一致,均匀分配)。

如果下述情况如何处理:

  1. 如果Consumer数量大于partition数量呢?
  2. 如果Consumer数量小于partition数量呢?

这两种情况,读者可自行测试。

但要注意如下情况:

  1. 如果Consumer数量比partition数量多,会有的Consumer闲置无法消费,这样是一个浪费。

  2. 如果Consumer数量小于partition数量会有一个Consumer消费多个partition

Kafkapartition上是不允许并发的。Consuemr数量建议最好是partition的整数倍。

还有一点,如果Consumer从多个partiton上读取数据,是不保证顺序性的。Kafka只保证一个partition的顺序性,跨partition是不保证顺序性的。增减 Consumer、broker、partition 会导致 Rebalance

6. Kafka 分区分配策略

Kafka中,同一个Group中的消费者对于一个Topic中的多个partition存在一定的分区分配策略——分区分配策略有如下两种:

  1. Range(默认)策略

  2. RoundRobin(轮询)策略

通过partition.assignment.strategy这个参数来设置。

6.1 Range strategy(范围分区)

Range策略是对每个主题而言的,首先对同一个主题里面的分区按照序号进行排序,并对消费者按照字母顺序进行排序。

假设我们有10个分区,3个消费者,排完序的分区将会是0,1,2,3,4,5,6,7,8,9;消费者线程排完序将会是C1-0, C2-0, C3-0

然后partitions的个数除于消费者线程的总数来决定每个消费者线程消费几个分区。如果除不尽,那么前面几个消费者线程将会多消费一个分区。

假如在 Topic1中有10个分区,3个消费者线程,10/3 = 3,而且除不尽,那么消费者线程C1-0将会多消费一个分区,所以最后分区分配的结果是这样的:

  1. C1-0将消费0,1,2,3分区

  2. C2-0将消费4,5,6分区

  3. C3-0将消费7,8,9分区

假如在Topic1中有11个分区,那么最后分区分配的结果看起来是这样的:

  1. C1-0将消费0,1,2,3分区

  2. C2-0将消费4, 5, 6, 7分区

  3. C3-0将消费8,9,10分区

假如有两个Topic:Topic1 和 Topic2,都有10个分区。那么,最后分区分配的结果看起来是这样的:

  1. C1-0将消费Topic10,1,2,3分区和Topic10,1,2,3分区

  2. C2-0将消费Topic14,5,6分区和Topic24,5,6分区

  3. C3-0将消费Topic17,8,9分区和Topic27,8,9分区

其实这样就会有一个问题,C1-0就会多消费两个分区,这就是一个很明显的弊端。

6.2 RoundRobin strategy(轮询分区)

轮询分区策略是把所有partition和所有Consumer线程都列出来,然后按照hashcode进行排序。

最后通过轮询算法分配partition给消费线程。如果所有Consumer实例的订阅是相同的,那么partition会均匀分布。

假如按照hashCode排序完的Topic / partitions组依次为:

  • T1一5
  • T1一3
  • T1-0
  • T1-8
  • T1-2
  • T1-1
  • T1-4
  • T1-7
  • T1-6
  • T1-9

消费者线程排序为:

  • C1-0
  • C1-1
  • C2-0
  • C2-1

最后的分区分配的结果为:

  • C1-0将消费T1-5, T1-2, T1-6分区
  • C1-1将消费T1-3, T1-1, T1-9分区
  • C2-0将消费T1-0, T1-4分区
  • C2-1将消费T1-8, T1-7分区

使用轮询分区策略必须满足两个条件:

  • 每个主题的消费者实例具有相同数量的流

  • 每个消费者订阅的主题必须是相同的

1. 什么时候会触发这个策略呢?

当出现以下几种情况时,Kafka会进行一次分区分配操作,也就是Kafka ConsumerRebalance

  • 同一个Consumer group内新增了消费者

  • 消费者离开当前所属的Consumer group,比如主动停机或者宕机

  • Topic新增了分区(也就是分区数量发生了变化)

Kafka ConsuemrRebalance机制规定了一个Consumer group下的所有Consumer如何达成一致来分配订阅Topic的每个分区。

而具体如何执行分区策略,就是前面提到过的两种内置的分区策略。而Kafka对于分配策略这块,提供了可插拔的实现方式,也就是说,除了这两种之外,我们还可以创建自己的分配机制。

2. 谁来执行Rebalance以及管理Consumergroup呢?

Consumer group如何确定自己的coordinator是谁呢,消费者向Kafka集群中的任意一个broker发送一个 GroupCoord inatorRequest请求,服务端会返回一个负载最小的broker节点的id,并将该broker设置为 coordinator

3. JoinGroup的过程

Rebalance之前,需要保证coordinator是已经确定好了的,整个Rebalance的过程分为两个步骤,Join和Syncjoin:表示加入到Consumer group中,在这一步中,所有的成员都会向coordinator发送 joinGroup的请求。

一旦所有成员都发了joinGroup请求,那么coordinator会选择一个Consumer担任leader角色,并把组成员信息和订阅信息发送给消费者:

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

  • protocol-metadata:序列化后的消费者的订阅信息

  • leader id:消费组中的消费者,coordinator会选择一个作为leader,对应的就是member id

  • member metadata:对应消费者的订阅信息

  • members: consumer group中全部的消费者的订阅信息

  • generation_id:年代信息,类似于ZooKeepe 中的epoch,对于每一轮Rebalancegeneration_id都会递增。主要用来保护consumer group,隔离无效的offset提交。也就是上一轮的consumer成员无法提交 offset到新的Consumer group中。

4. Synchronizing Group State 阶段

完成分区分配之后,就进入了Synchronizing Group Stat 阶段,主要逻辑是向GroupCoordinator发送SyncGroupRequest请求,并且处理SyncGroupResponse响应,简单来说,就是leader将消费者对应的 partition分配方案同步给Consumer group中的所有Consumer

kafka topic partition设置,免费专栏,kafka,java,分布式,后端,运维开发

每个消费者都会向coordinator发送syncgroup请求,不过只有leader节点会发送分配方案,其他消费者只是打打酱油而已。

leader把方案发给coordinator以后,coordinator会把结果设置到SyncGroupResponse中。这样所有成员都知道自己应该消费哪个分区。

Consumer group的分区分配方案是在客户端执行的!Kafka将这个权利下放给客户端主要是因为这样做可以有更好的灵活性。文章来源地址https://www.toymoban.com/news/detail-823649.html

7.参考文献

  1. https://dongguabai.blog.csdn.net/article/details/86536894

到了这里,关于全网最详细地理解Kafka中的Topic和Partition以及关于kafka的消息分发、服务端如何消费指定分区、kafka的分区分配策略(range策略和RoundRobin策略)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Kafka某Topic的部分partition无法消费问题

    今天同事反馈有个topic出现积压。于是上kfk管理平台查看该topic对应的group。发现6个分区中有2个不消费,另外4个消费也较慢,总体lag在增长。查看服务器日志,日志中有rebalance 12 retry 。。。Exception,之后改消费线程停止。 查阅相关rebalance资料:   分析Rebalance 可能是 Consu

    2024年02月12日
    浏览(44)
  • kafka中Topic、Partition、Groups、Brokers概念辨析

    kafka消息队列有两种消费模式,分别是 点对点模式 和 订阅/发布模式 。具体比较可以参考Kafka基础–消息队列与消费模式。 下图是一个 点对点 的Kafka结构示意图,其中有以下几个部分: producer:消息生产者 consumer:消息消费者 Topic:消息主题 partition:主题内分区 Brokers:消

    2024年02月04日
    浏览(57)
  • kafka消费报错 UNKNOWN_TOPIC_OR_PARTITION

    查看topic 发现分区数量为:1 我们是多个消费服务

    2024年02月11日
    浏览(61)
  • 大数据篇Kafka消息队列指定Topic打印Key、Value、Offset和Partition

    说到Apache Kafka消息传递系统时,以下是一些关键概念的解释: Key(键):Kafka消息由Key和Value组成。Key是一个可选的字段,它通常用于消息的路由和分区策略。Key的目的是确保具有相同Key的消息被写入同一个分区。当消费者接收到消息时,可以使用Key来进行消息处理和路由操

    2024年02月16日
    浏览(52)
  • 关于java中的多态和对实例化对象以及向上、向下转型的一些理解

    java面向对象三大特征即为:继承封装多态。而多态需要三大必要条件。分别是:继承、方法重写、父类引用指向子类对象。我们先一个一个来理解。 1、首先是继承和重写。这个很简单。因为多态就是建立在不同的重写之上的。也就是说多态就是在使用着一个方法的不同重写

    2024年02月02日
    浏览(43)
  • 全面理解java中的构造方法以及this关键字的用法(超详细)

    Hello,各位铁汁们!我是小🐟儿哈!今天我又来更新我的Java基础学习博客了。 本篇主要内容概述: 1、🍚如何用构造方法初始化对象 2、🍚为啥要有this这个 3、🍚this.属性名访问成员变量、成员方法 4、🍚this.方法名 || this.()的用法 目录 初识构造方法  构造方法的使

    2023年04月09日
    浏览(62)
  • Kafka系列之:基于Apache Kafka Connect实现端到端topic数据字段级加密的详细方法

    与其他通信工具一样,加密在 Apache Kafka 中很有价值,可以保护数据。 希望通过与 Apache Kafka Connect 集成来加密数据来实现这一目标。 Kafka 可以利用多种安全功能,从身份验证和授权到基于 TLS 的数据进出 Kafka 主题的线上流量加密。尽管这些措施可以保护传输中的数据,但它

    2024年02月13日
    浏览(47)
  • 理解RabbitMQ中的AMQP-0-9-1模型,全网最全

    Type:交换器的类型。 Durability:(交换器)持久化特性,如果启动此特性,则Broker重启后交换器依然存在,否则交换器会被删除。 Auto-delete:是否自动删除,如果启用此特性,当最后一个队列解除与交换器的绑定关系,交换器会被删除。 Arguments:可选参数,一般配合插件或者

    2024年04月26日
    浏览(42)
  • 关于访问后端接口报404的问题——全网最详细的404错误详解

    当我们通过前端向后端发起一个请求调用后端接口时,经常会遇到404的问题。网上关于对404问题介绍的一大堆,其实404问题的本质就两点。 在介绍404问题之前先温习一个小的知识点——项目访问路径 项目访问路径:就是定位一个项目的路径,可以理解为项目名,但是一般这

    2024年02月02日
    浏览(40)
  • 【mysql进阶-彩蛋篇】深入理解顺序io和随机io(全网最详细篇)

    MySql系列整体栏目 内容 链接地址 【一】深入理解mysql索引本质 https://blog.csdn.net/zhenghuishengq/article/details/121027025 【二】深入理解mysql索引优化以及explain https://blog.csdn.net/zhenghuishengq/article/details/124552080 【三】深入理解mysql的索引分类,覆盖索引(失效),回表,MRR https://bl

    2024年02月05日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包