Kafka核心概念、数据存储设计及Partition数据文件 生产者负载均衡策略、批量发送技巧、消息压缩手段、消费者设计

关注公众号,发送 “面试题” 即可免费领取一份超全的面试题PDF文件!!!!

1、kafka的概念

Kafka 是一个开源的分布式流处理平台,最初由LinkedIn开发,后来成为Apache软件基金会的一个顶级项目。它被设计为高吞吐量、可扩展、持久化的分布式发布-订阅消息系统。以下是 Kafka 的一些关键概念:

  1. 消息(Message): Kafka 是一个消息系统,数据以消息的形式进行传递。消息可以是任何形式的数据,通常包含键值对,以及其他元数据。

  2. 主题(Topic): 消息按照主题进行分类,主题是消息的逻辑容器。生产者发布消息到特定主题,而消费者则从感兴趣的主题订阅消息。

  3. 分区(Partition): 主题可以被划分为多个分区,每个分区是一个有序、不可变的消息序列。分区允许 Kafka 在水平方向上扩展,提高并行性和吞吐量。

  4. 生产者(Producer): 生产者是负责将消息发布到 Kafka 主题的应用程序。生产者将消息发送到指定的主题,并可以选择指定消息发送的分区。

  5. 消费者(Consumer): 消费者是从 Kafka 主题订阅消息的应用程序。消费者可以以不同的方式处理消息,例如存储、转发、实时处理等。

  6. 偏移量(Offset): 每个分区中的每条消息都有一个唯一的偏移量,用于标识消息在分区中的位置。消费者使用偏移量来追踪已经消费的消息位置。

  7. 代理或服务器(Broker): Kafka 集群由多个 Broker 组成,每个 Broker 是一个独立的 Kafka 服务器。Brokers 负责存储消息,处理生产者和消费者的请求,并协调集群中的分区。

  8. 复制(Replication): 为了提供高可用性和容错性,Kafka 支持将每个分区的消息复制到多个 Broker 上。每个分区有一个 Leader 和零个或多个 Followers。

  9. Zookeeper: Kafka 依赖 Zookeeper 来进行集群协调、元数据管理、Leader 选举等任务。

  10. 水平扩展: Kafka 具有良好的水平扩展性,通过增加 Broker、分区等方式来适应更大规模的数据和负载。

  11. 消费者组(Consumer Group): 消费者可以组成一个消费者组,共同消费一个主题的消息。每个分区只能被一个消费者组内的一个消费者消费。

  12. 日志(Log): Kafka 将消息以日志的形式存储,每个分区对应一个日志文件。这种存储方式保证了消息的顺序性和持久性。

Kafka 的这些概念共同构建了一个高效、可靠的分布式消息系统,广泛用于构建实时数据流处理和日志收集等场景。

当我们谈论 Kafka 时,可以将其想象成一个先进的邮局系统,其中有一些重要的角色和概念:
邮件(消息):
在 Kafka 里,我们发送和接收的是消息,就像我们在邮局中发送和收到邮件一样。这些消息可以包含任何你想要传递的信息,比如文本、数据等。
邮箱(主题):
消息按照主题进行分类,就好比我们的邮局有不同的邮箱,每个邮箱对应一个主题。发送者把消息放入指定的邮箱(主题),而接收者从感兴趣的邮箱中取出消息。
信箱的分隔(分区):
为了更好地处理大量的消息,每个邮箱(主题)都被分成了若干个小的部分,每个部分叫做分区。这样,处理消息的时候就可以更灵活、更高效。
寄件人(生产者):
寄件人就是消息的发送者,我们称之为生产者。生产者将消息投递到指定的邮箱(主题),并选择把消息放入哪个分区。
收件人(消费者):
收件人是消息的接收者,我们称之为消费者。消费者从感兴趣的邮箱(主题)中取出消息,处理或者存储这些消息。
信件的位置标记(偏移量):
每个消息都有一个唯一的标记,就像邮件上的邮戳一样,我们称之为偏移量。消费者通过偏移量追踪已经处理过的消息,确保不会漏掉或者重复处理。
邮局(Broker):
邮局就是整个 Kafka 系统,由多个邮局(Broker)组成。每个邮局都有自己的邮箱(主题)和信箱的分隔(分区),处理消息的任务由这些邮局共同协调完成。
邮局的副本(复制):
为了确保消息的安全性,每个邮箱(主题)的消息会被复制到多个邮局(Broker)。每个邮箱有一个主要的邮局(Leader),其他的邮局是备用(Followers)。
邮局管理员(Zookeeper):
邮局管理员就像是整个邮局系统的管理者,负责协调各个邮局的工作、管理邮箱的信息和处理一些系统级别的任务。
邮局的扩展(水平扩展):
如果我们的邮局负载过大,我们可以通过增加更多的邮局(Broker)或者分隔更多的邮箱(主题)来提高处理能力,就像扩建邮局一样。

2、Kafka数据存储设计

Kafka的数据存储设计采用了日志文件的方式,主要设计特点如下:

  1. 日志文件(Log): Kafka将消息按照日志文件的形式存储,每个主题的每个分区都对应一个日志文件。这种日志文件的设计使得消息以追加的方式存储,确保了消息的有序性和持久性。

  2. 分区(Partition): 主题可以被划分为多个分区,每个分区对应一个日志文件。引入分区的设计允许Kafka在水平方向上进行扩展,提高了并行性和吞吐量。

  3. 分段存储(Segment): 日志文件被划分为多个分段,每个分段对应一个时间范围或者大小限制。这种分段存储的方式允许Kafka的日志文件逐渐增长而不会无限制地变大,便于管理和维护。

  4. 索引文件(Index): 为了加速消息的查找,每个分段都有一个相应的索引文件。索引文件包含了偏移量范围和消息key的信息,以便快速定位到某个偏移量对应的消息。

  5. 顺序读写: 每个分段内部的消息是按照顺序进行读写的,保证了消息在分段文件中的物理存储顺序与逻辑上的Offset顺序一致。这对于顺序性的消息处理非常重要。

  6. 分段索引和稀疏存储: 为每个分段的数据文件建立了索引文件,采用了稀疏存储的方式。这意味着并不为每条消息都建立索引,而是通过间隔一定字节数建立一条索引。这样的设计在一定程度上节省了索引文件的空间占用。

  7. 复制(Replication): 为了提供高可用性和容错性,每个分区的消息都会被复制到多个Broker上。Leader-Follower模型确保了复制的一致性和容错性。

2.1 partition 的数据文件( offset,MessageSize,data )

假设有一个 Kafka 主题(Topic)叫做 "example_topic",该主题有两个分区(Partition),分别为 Partition 0 和 Partition 1。

Offset(偏移量):

对于 Partition 0,数据文件记录的消息如下:

Offset: 0, MessageSize: 50, Data: "Hello, Kafka!"
Offset: 1, MessageSize: 45, Data: "This is a message."

对于 Partition 1,数据文件记录的消息如下:

Offset: 0, MessageSize: 60, Data: "Another message for Partition 1."

MessageSize(消息大小):

假设消息的大小是以字节为单位计算的,上述示例中的 MessageSize 属性表示了每条消息的存储空间占用。

Data(消息内容):

Data 属性存储了实际的消息内容。例如,对于 Offset 0 的消息,Data 包含了 "Hello, Kafka!" 这段文本。

这些属性的具体使用场景:

消息追加: 当新消息到达时,例如有一条新消息 "New message arrived!",它会以追加的方式写入数据文件,附上适当的Offset和MessageSize。

消息读取: 当需要读取消息时,通过索引等机制能够快速定位到特定Offset的消息。比如,可以快速读取 Partition 0 的 Offset 1 处的消息内容。

存储管理: MessageSize 属性可用于估算存储空间的需求。管理员可以通过监测消息的大小来优化存储分配。

消息索引: Offset等属性构成了消息的逻辑标识,用于建立索引和支持快速的消息查找操作。在实际应用中,Kafka会建立索引以支持快速的读取和查找操作。

2.2 数据文件分段 segment

数据文件的分段设计是 Kafka 中保证高效、有序存储消息的重要组成部分。以下是关于数据文件分段(Segment)的一些详细说明:

顺序读写:

每个数据文件内部的消息是按照顺序进行读写的。新的消息以追加的方式写入文件的末尾,这保证了消息在文件中的物理存储顺序与逻辑上的 Offset 顺序一致。顺序读写有助于提高读写性能,并且支持Kafka作为有序消息系统的核心特性。

分段命名:

数据文件被切分成多个段(Segment),每个段对应一个时间范围或者大小限制。每个段都有一个唯一的标识,通常采用该段中最小的 Offset 来命名,以确保唯一性。这种分段的设计使得文件能够逐渐增长而不会无限制地变大,便于管理和维护。

二分查找:

由于每个分段内部的消息是有序的,Kafka可以通过二分查找的方式在段内快速定位到目标 Offset 所对应的消息位置。这种查找方式在读取消息时提供了较高的效率,特别是当分段文件较大时。

这样的设计使得Kafka在处理大规模数据流时能够高效地进行顺序读写和查找操作。新消息追加到新的分段,而旧的分段保持不变,确保了数据文件的分段存储,进而提高了Kafka系统的整体性能和可维护性。

让我们通过一个简单的示例来说明数据文件分段的概念:

假设有一个 Kafka 主题(Topic)叫做 "log_messages",该主题有一个分区(Partition),分区的数据文件按照分段设计,每个分段对应一个时间范围。初始时,有两个分段,分别为 Segment-1 和 Segment-2。

顺序读写:

当有新消息到达时,它们会按照顺序被追加到当前活跃的分段。例如,新消息 "Message 1" 和 "Message 2" 被依次追加到 Segment-1 的末尾。

Segment-1:
Offset: 0, Message: "Message 1"
Offset: 1, Message: "Message 2"

随着时间的推移,当 Segment-1 达到一定的大小或时间限制时,Kafka 将关闭当前的 Segment-1,并创建一个新的分段 Segment-3。

分段命名和切换:

新创建的 Segment-3 将成为新的活跃分段,用于接收后续的消息。此时,系统中的分段变为 Segment-2 和 Segment-3。

Segment-2:
Offset: 2, Message: "Message 3"
Offset: 3, Message: "Message 4"Segment-3: (新的活跃分段)

随着消息的不断追加,Segment-3 会逐渐积累消息。

二分查找:

当需要读取某个特定 Offset 的消息时,Kafka 可以利用二分查找在活跃分段中快速定位到目标消息。例如,如果需要读取 Offset 1 的消息,系统会执行二分查找并定位到 Segment-1 中的相应位置。

3、生产者设计

3.1 生产者如何做负载均衡

Kafka 生产者的负载均衡主要是通过以下两个方面来实现的:

1.分区选择策略: 生产者在发送消息时需要选择将消息发送到哪个分区。Kafka 提供了多种分区选择策略,生产者可以根据业务需求选择合适的策略。

分区选择策略和负载均衡:

  • 由于消息的 Topic 由多个 Partition 组成,而这些 Partition 会均衡分布到不同的 Broker 上,为了充分利用整个 Broker 集群的性能,提高消息的吞吐量,生产者可以采用灵活的分区选择策略,实现负载均衡。

  • 随机分区选择: 生产者可以选择随机将消息发送到不同的分区,确保消息在各个分区之间均匀分布,以达到负载均衡的效果。

  • 哈希分区选择: 另一种常见的方式是通过消息的关键信息进行哈希计算,将相同哈希值的消息发送到同一个分区。这种方式适用于要求相关消息存储在同一分区的业务场景。

  • 这样的设计确保了生产者在发送消息时能够充分利用 Broker 集群的各个 Partition,提高整体系统的性能和并行性。

常见的分区选择策略包括:

  • 轮询策略: 生产者按照轮询的方式选择分区,确保消息均匀地分布在各个分区中。

  • 哈希策略: 使用消息的关键信息进行哈希计算,将相同哈希值的消息发送到同一个分区,适用于要求相关消息存储在同一分区的场景。

  • 随机策略: 生产者随机选择一个分区,适用于无特定需求的负载均衡。

2.Producer 实例多线程: 生产者实例是线程安全的,因此可以通过创建多个生产者实例,并在每个实例上运行多个线程的方式来提高并行性。每个线程负责发送消息到不同的分区,这样可以实现消息的并行发送,提高整体吞吐量。

示例代码(Java):

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;public class KafkaProducerExample {public static void main(String[] args) {// 配置 Kafka 生产者// ...// 创建 Kafka 生产者实例Producer<String, String> producer = new KafkaProducer<>(/* 配置参数 */);// 启动多个线程并创建多个生产者实例for (int i = 0; i < 5; i++) {new Thread(() -> {// 创建生产者实例Producer<String, String> threadProducer = new KafkaProducer<>(/* 配置参数 */);// 在每个线程中发送消息到指定分区for (int j = 0; j < 100; j++) {String message = "Message-" + j;// 选择分区或使用默认分区选择策略ProducerRecord<String, String> record = new ProducerRecord<>("example_topic", message);// 发送消息threadProducer.send(record);}// 关闭生产者实例threadProducer.close();}).start();}// 关闭主线程中的生产者实例producer.close();}
}

3.2 生产者 如何做到批量发送

生产者在 Kafka 中通过批量发送消息可以提高吞吐量,减少网络开销。这通常是通过两个主要的配置参数来实现的:batch.size 和 linger.ms。

batch.size 参数:

batch.size 参数指定了一个批次中消息的大小上限。当生产者积累了足够多的消息达到或超过这个大小时,批量发送消息。较大的 batch.size 值通常能够提高吞吐量,但会增加延迟,因为需要等待足够的消息填充一个批次。 示例配置:

producer.batch.size=16384

linger.ms 参数:

linger.ms 参数指定了生产者在发送批次之前等待的时间上限。即使批次未达到 batch.size,当等待时间超过 linger.ms 时,生产者也会发送当前积累的消息。通过设置较小的 linger.ms 值,可以降低延迟,但可能会影响吞吐量。

示例配置:

producer.linger.ms=5

示例代码(Java):

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;import java.util.Properties;public class KafkaProducerExample {public static void main(String[] args) {Properties properties = new Properties();// 配置其他 Kafka 生产者参数...// 设置批量发送的大小和等待时间properties.put("batch.size", 16384);properties.put("linger.ms", 5);// 创建 Kafka 生产者实例Producer<String, String> producer = new KafkaProducer<>(properties);// 发送批量消息for (int i = 0; i < 100; i++) {String message = "Message-" + i;ProducerRecord<String, String> record = new ProducerRecord<>("example_topic", message);// 发送消息到 Kafkaproducer.send(record);}// 关闭生产者实例producer.close();}
}

在上述示例中,通过设置 batch.sizelinger.ms 参数,生产者将会在满足批量大小或等待时间的条件下批量发送消息,从而提高了整体的吞吐量。具体的参数值可以根据实际需求和性能测试进行调整。

生产者的消息压缩

Kafka 生产者提供了消息压缩的功能,通过压缩消息可以有效减少网络传输的数据量,降低网络带宽的使用,提高整体的性能。在 Kafka 中,压缩是通过配置 compression.type 参数实现的。

compression.type 参数:

  • compression.type 参数用于设置消息的压缩算法。常见的压缩算法包括:

  • none: 不使用压缩,消息以原始形式发送。

  • gzip: 使用 Gzip 压缩算法。

  • snappy: 使用 Snappy 压缩算法。

  • lz4: 使用 LZ4 压缩算法。

示例配置:

producer.compression.type=gzip

压缩级别(可选):

  • 对于 Gzip 压缩算法,可以通过配置 compression.level 参数设置压缩级别,数值越大表示压缩比越高,但同时也会增加 CPU 消耗。

示例配置:

producer.compression.level=3

示例代码(Java):

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;import java.util.Properties;public class KafkaProducerExample {public static void main(String[] args) {Properties properties = new Properties();// 配置其他 Kafka 生产者参数...// 设置压缩算法properties.put("compression.type", "gzip");// 创建 Kafka 生产者实例Producer<String, String> producer = new KafkaProducer<>(properties);// 发送压缩消息for (int i = 0; i < 100; i++) {String message = "Message-" + i;ProducerRecord<String, String> record = new ProducerRecord<>("example_topic", message);// 发送消息到 Kafkaproducer.send(record);}// 关闭生产者实例producer.close();}
}

在上述示例中,通过设置 compression.type 参数,生产者将使用 Gzip 压缩算法对消息进行压缩。压缩算法的选择通常取决于对性能和网络带宽的平衡,不同的场景可能选择不同的压缩算法。

4.消费者设计

消费者在 Kafka 中负责从主题(Topic)订阅消息,并进行相应的处理。以下是 Kafka 消费者设计的关键方面:

  1. 消费者组:

    • 消费者可以组成一个消费者组,每个消费者组可以有多个消费者。Kafka 通过消费者组来实现消息的负载均衡和水平扩展。每个分区只能由同一个消费者组中的一个消费者来消费,但一个消费者组可以同时消费多个分区。

  2. 订阅主题:

    • 消费者通过调用 subscribe 方法订阅一个或多个主题。可以使用正则表达式进行模式匹配,实现对多个相关主题的订阅。

    示例代码(Java):

    consumer.subscribe(Arrays.asList("example_topic"));
    
  3. 消息拉取和轮询:

    • 消费者通过轮询(poll)机制从 Kafka 服务器拉取消息。在每次轮询中,消费者可以一次性拉取多条消息,并在本地进行处理。轮询的频率由配置参数 max.poll.interval.ms 控制。

    示例代码(Java):

    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
    for (ConsumerRecord<String, String> record : records) {// 处理每条消息System.out.printf("Consumed record with key %s and value %s%n", record.key(), record.value());
    }
    
  4. 消息处理和业务逻辑:

    • 消费者需要实现消息的具体处理逻辑。这包括对消息的解析、业务逻辑的执行、数据存储等操作。处理逻辑的复杂性和实现方式取决于具体的应用场景。

    示例代码(Java):

    for (ConsumerRecord<String, String> record : records) {// 处理每条消息的业务逻辑String message = record.value();processMessage(message);
    }
    
  5. 消息提交和偏移量管理:

    • 消费者需要负责管理偏移量(offset)以跟踪已消费的消息。偏移量表示消费者在分区中的位置。Kafka 提供了自动和手动两种提交偏移量的方式。自动提交由 Kafka 客户端负责,而手动提交则由应用程序控制。

    示例代码(Java):

    // 手动提交偏移量
    consumer.commitSync();
    
  6. 异常处理和重平衡:

    • 消费者需要处理可能发生的异常,例如网络故障、Kafka 集群的重启等情况。此外,当消费者组的成员发生变化时(如有新的消费者加入或有消费者退出),可能触发消费者的重平衡。在重平衡期间,Kafka 会重新分配分区给消费者,确保每个分区只被一个消费者消费。

    示例代码(Java):

    try {while (true) {ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));// 处理消息...}
    } catch (WakeupException e) {// 处理消费者被唤醒的异常
    } finally {consumer.close();
    }
    
  7. 性能调优:

    • 消费者的性能也可以通过配置进行调优。例如,可以设置 max.poll.records 控制每次轮询拉取的最大消息数量,以影响消费者的吞吐量。

    示例代码(Java):

    properties.put("max.poll.records", 500);
    

Kafka 消费者的设计需要考虑到消息处理的逻辑、偏移量管理、异常处理以及重平衡等方面,以确保消费者能够稳定、高效地消费消息。

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

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

相关文章

SpringAop实现访问日志功能的添加

AOP 是 Spring 体系中非常重要的两个概念之一&#xff08;另外一个是 IoC&#xff09;&#xff0c;今天这篇文章就来带大家通过实战的方式&#xff0c;在编程猫 SpringBoot 项目中使用 AOP 技术为 controller 层添加一个切面来实现接口访问的统一日志记录。 #一、关于 AOP AO…

讯飞星火V3.5发布,一场大模型的奇幻之旅(深度体验讯飞星火V3.5)

在去年的人工智能领域&#xff0c;大模型无疑是最炙手可热的技术话题。其强大的数据处理和深度学习能力&#xff0c;为众多领域带来了革命性的变革。而其中&#xff0c;讯飞星火表现尤为出色&#xff0c;成为了行业的翘楚&#xff0c;得到了大量的用户认可&#xff0c;其中&…

day38 ● 509. 斐波那契数 ● 70. 爬楼梯 ● 746. 使用最小花费爬楼梯

动态规划是前一个状态推导过来的&#xff0c;贪心是局部最优解。 class Solution { public:int fib(int n) {int a0;int b1;int res0;if(n1) return 1;for(int i2;i<n;i){resab;ab;bres;}return res;} }; 可以由前面状态推出后面状态&#xff0c;是动态规划。由于始终只要后…

C++20 协程原理与应用

协程 要想了解协程&#xff0c;最好先搞清楚进程&#xff0c;线程&#xff0c;这样才能将三者区分开来&#xff01; 进程 vs 线程 vs 协程 进程线程协程切换者操作系统操作系统用户&#xff08;编程者&#xff09;切换时机根据操作系统自己的切换策略&#xff0c;用户不感知根…

最小化安装BCLinux-for-Euler-21.10-dvd-x86_64-230731版

本文记录最小化安装BCLinux-for-Euler-21.10-dvd-x86_64-230731版。 一、镜像获取 1、下载镜像 移动云官方网站 最新镜像为2023-11-02 15:04:56更新的BCLinux-for-Euler-21.10-dvd-x86_64-230731版 直接下载地址&#xff1a;https://mirrors.cmecloud.cn/bclinux/oe21.10/I…

【Linux】线程池的简易实现(懒汉模式)

文章目录 前言一、懒汉方式1.普通模式1.线程安全模式 二、源代码1.Task.hpp(要执行的任务)2.ThreadPool.hpp(线程池)3.Main.cpp 前言 线程池: 一种线程使用模式。线程过多会带来调度开销&#xff0c;进而影响缓存局部性和整体性能。而线程池维护着多个线程&#xff0c;等待着监…

java之mybatis入门

大前题 正确创建好了springboot工程&#xff0c;极其依赖 配置数据库连接 application.yml spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/cangqiongusername: rootpassword: rootlombok Data 自动生成代码&#xff08…

【免费分享】概率神经网络的分类预测--基于PNN的变压器故障诊断

主要内容 ​《MATLAB神经网络43个案例分析》共有43章&#xff0c;内容涵盖常见的神经网络&#xff08;BP、RBF、SOM、Hopfield、Elman、LVQ、Kohonen、GRNN、NARX等&#xff09;以及相关智能算法&#xff08;SVM、决策树、随机森林、极限学习机等&#xff09;。同时&#x…

Java 对部分接口返回数据进行加密,或其他处理

业务场景&#xff1a;后端项目中分为PC端和移动端接口&#xff0c;移动端为例如 mobile 开头的URl&#xff0c;需求为调用移动端接口时&#xff0c;对返回数据进行加密&#xff0c;PC端不加密 import cn.hutool.core.date.DatePattern; import cn.hutool.json.JSONConfig; impo…

系统架构设计师-22年-下午题目

系统架构设计师-22年-下午题目 更多软考知识请访问 https://ruankao.blog.csdn.net/ 试题一必答&#xff0c;二、三、四、五题中任选两题作答 试题一 (25分) 说明 某电子商务公司拟升级其会员与促销管理系统&#xff0c;向用户提供个性化服务&#xff0c;提高用户的粘性。…

全流程机器视觉工程开发(三)任务前瞻 - 从opencv的安装编译说起,到图像增强和分割

前言 最近开始做这个裂缝识别的任务了&#xff0c;大大小小的问题我已经摸得差不多了&#xff0c;然后关于识别任务和分割任务我现在也弄的差不多了。 现在开始做正式的业务&#xff0c;也就是我们说的裂缝识别的任务。作为前言&#xff0c;先来说说场景&#xff1a; 现在相…

0131-2-关于事件捕获和冒泡

关于事件捕获和冒泡 DOM事件流分为三个阶段&#xff1a;捕获阶段、目标阶段、冒泡阶段 点击目标元素后&#xff0c;不会马上触发目标元素&#xff0c;而是先执行事件捕获&#xff0c;从顶部逐步到目标元素&#xff1b;处于目标阶段的时候触发目标元素&#xff1b;最后冒泡阶段…

如何在Raspberry Pi上启用SSH并结合cpolar内网穿透实现公网远程访问本地树莓派

文章目录 如何通过 SSH 连接到树莓派步骤1. 在 Raspberry Pi 上启用 SSH步骤2. 查找树莓派的 IP 地址步骤3. SSH 到你的树莓派步骤 4. 在任何地点访问家中的树莓派4.1 安装 Cpolar4.2 cpolar进行token认证4.3 配置cpolar服务开机自启动4.4 查看映射到公网的隧道地址4.5 ssh公网…

我的创作纪念日和前端碎碎念

机缘 作为一个前端开发者&#xff0c;我一直热衷于将设计和技术相结合&#xff0c;尽可能提升用户体验。我最初成为创作者的初心源于学习记录&#xff0c;把创作当作一个笔记&#xff0c;希望把自己遇到的问题&#xff0c;以及学习到的实用技巧记录下来&#xff0c;方便学习回…

Qt Excel读写 - QXlsx的安装配置以及测试

Qt Excel读写 - QXlsx的安装配置以及测试 引言一、安装配置二、简单测试 引言 Qt无自带的库处理Excel 文件&#xff0c;但可通过QAxObject 借助COM接口进行Excel的读写1。亦可使用免费的开源第三方库&#xff1a;QXlsx&#xff0c;一个基于Qt库开发的用于读写Microsoft Excel文…

CUDA下载安装教程,新手详细

目录 一、下载二、安装三、 设置环境变量四、补丁安装 由于项目需要安装特定版本的CUDA&#xff0c;现记录安装过程。 一、下载 进入官方下载地址&#xff1a;https://developer.nvidia.com/cuda-toolkit-archive 选择自己需要的版本。如果没有明确要求版本号&#xff0c;那么…

安卓视图基础

目录 设置视图的宽高 设置视图的间隔 设置视图的对齐方式 设置视图的宽高 设置视图的间隔 设置视图的对齐方式 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"a…

聊聊java中的Eureka和Nacos

本文主要来自于黑马课程中 1.提供者与消费者 在服务调用关系中&#xff0c;会有两个不同的角色&#xff1a; 服务提供者&#xff1a;一次业务中&#xff0c;被其它微服务调用的服务。&#xff08;提供接口给其它微服务&#xff09; 服务消费者&#xff1a;一次业务中&#xff0…

javaweb项目,springboot幼儿园健康管理系统,界面美观,增删改查。

javaweb项目&#xff0c;幼儿园健康管理系统&#xff0c;界面美观&#xff0c;增删改查。 管理员&#xff0c;老师&#xff0c;学生三个角色。 功能&#xff1a;权限管理&#xff0c;咨询列表&#xff0c;教师列表&#xff0c;班级列表&#xff0c;健康档案列表&#xff0c;评…

python数据类型-列表

1 python中列表的定义 python中列表是一种有序和可更改的集合&#xff0c;允许重复的成员&#xff0c;列表中的元素之间数据类型可以不同&#xff08;元素之间数据类型可以不相同&#xff0c;这一点和其它的面向对象的开发语言有很大的不同&#xff0c;如C#、Java&#xff09;…