当前位置: 首页 > news >正文

kafka进阶_3.消费消息

文章目录

  • 一、消费消息概览
    • 1.1、消费示例代码
    • 1.2、消费过程
  • 二、消费者组
    • 2.1、push & pull
    • 2.2、消费者组
  • 三、调度器Coordinator
  • 四、消费者分配策略
    • 4.1、引言
    • 4.2、分配基本流程
    • 4.3、分配策略
      • 4.3.1、轮询分配策略
      • 4.3.2、轮询分配策略
  • 五、消费偏移量
    • 5.1、起始偏移量
    • 5.2、指定偏移量消费
    • 5.3、偏移量提交
      • 5.3.1、自动提交
      • 5.3.2、手动提交
    • 5.4、偏移量的保存
  • 六、消费者事务
    • 6.1、消费者事务原理
    • 6.2、示例代码

如果想了解kafka基础架构、生产者架构和kafka存储消息可以参考 kafka基础、 Kafka进阶_1.生产消息和 kafka进阶_2.存储消息。

一、消费消息概览

1.1、消费示例代码

public class KafkaConsumerTest {public static void main(String[] args) {// TODO 创建消费者配置参数集合Map<String, Object> paramMap = new HashMap<>();paramMap.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");paramMap.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());paramMap.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());paramMap.put(ConsumerConfig.GROUP_ID_CONFIG, "test");// TODO 通过配置,创建消费者对象KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(paramMap);// TODO 订阅主题consumer.subscribe(Collections.singletonList("test"));// TODO 消费数据final ConsumerRecords<String, String> poll = consumer.poll(Duration.ofMillis(100));// TODO 遍历数据for (ConsumerRecord<String, String> record : poll) {System.out.println( record.value() );}// TODO 关闭消费者consumer.close();}
}

主要的属性配置:

参数名参数作用类型推荐值
bootstrap.servers集群地址必须
key.deserializer对数据Key进行反序列化的类完整名称必须Kafka提供的字符串反序列化类:StringSerializer
value.deserializer对数据Value进行反序列化的类完整名称必须Kafka提供的字符串反序列化类:ValueSerializer
group.id消费者组ID,用于标识完整的消费场景,一个组中可以包含多个不同的消费者对象

1.2、消费过程

  消费者消费数据时,一般情况下,只是设定了订阅的主题名称,那是如何消费到数据的呢。我们这里说一下服务端拉取数据的基本流程:

在这里插入图片描述

  1. 服务端获取到用户拉取数据的请求:Kafka消费客户端会向Broker发送拉取数据的请求FetchRequest,服务端Broker获取到请求后根据请求标记FETCH交给应用处理接口KafkaApis进行处理。
  2. 通过副本管理器拉取数据:副本管理器需要确定当前拉取数据的分区,然后进行数据的读取操作。
  3. 判定首选副本:2.4版本前,数据读写的分区都是Leader分区,从2.4版本后,kafka支持Follower副本进行读取。主要原因就是跨机房或者说跨数据中心的场景,为了节约流量资源,可以从当前机房或数据中心的副本中获取数据。这个副本称之为首选副本。
  4. 拉取分区数据:Kafka的底层读取数据是采用日志段LogSegment对象进行操作的。
  5. 零拷贝:为了提高数据读取效率,Kafka的底层采用nio提供的FileChannel零拷贝技术,直接从操作系统内核中进行数据传输,提高数据拉取的效率。

二、消费者组

  从数据处理的角度来讲,消费者和生产者的处理逻辑都相对比较简单。Producer生产者的基本数据处理逻辑就是向Kafka发送数据,并获取Kafka的数据接收确认响应。

在这里插入图片描述

而消费者的基本数据处理逻辑就是向Kafka请求数据,并获取Kafka返回的数据。

在这里插入图片描述
  逻辑确实很简单,但是Kafka为了能够构建高吞吐,高可靠性,高并发的分布式消息传输系统,所以在很多细节上进行了扩展和改善:比如生产者可以指定分区,可以异步和同步发送数据,可以进行幂等性操作和事务处理。对应的,消费者功能和处理细节也进行了扩展和改善。

2.1、push & pull

  Kafka的主题如果就一个分区的话,那么在硬件配置相同的情况下,消费者Consumer消费主题数据的方式没有什么太大的差别。

在这里插入图片描述
  不过,Kafka为了能够构建高吞吐,高可靠性,高并发的分布式消息传输系统,它的主题是允许多个分区的,那么就会发现不同的消费数据的方式区别还是很大的。

1、如果数据由Kafka进行推送(push),那么多个分区的数据同时推送给消费者进行处理,明显一个消费者的消费能力是有限的,那么消费者无法快速处理数据,就会导致数据的积压,从而导致网络、存储等资源造成极大的压力,影响吞吐量和数据传输效率。

在这里插入图片描述
2.如果kafka的分区数据在内部可以存储的时间更长一些,再由消费者根据自己的消费能力向kafka申请(拉取)数据,那么整个数据处理的通道就会更顺畅一些。Kafka的Consumer就采用的这种拉取数据的方式。

在这里插入图片描述

2.2、消费者组

  消费者可以根据自身的消费能力主动拉取Kafka的数据,但是毕竟自身的消费能力有限,如果主题分区的数据过多,那么消费的时间就会很长。对于kafka来讲,数据就需要长时间的进行存储,那么对Kafka集群资源的压力就非常大。如果希望提高消费者的消费能力,并且减少kafka集群的存储资源压力。所以有必要对消费者进行横向伸缩,从而提高消息消费速率。

在这里插入图片描述
  不过这么做有一个问题,就是每一个消费者是独立,那么一个消费者就不能消费主题中的全部数据,简单来讲,就是对于某一个消费者个体来讲,主题中的部分数据是没有消费到的,也就会认为数据丢了,这个该如何解决呢?那如果我们将这多个消费者当成一个整体,是不是就可以了呢?这就是所谓的消费者组 Consumer Group。在kafka中每个消费者都对应一个消费组,消费者可以是一个线程,一个进程,一个服务实例,如果kafka想要消费消息,那么需要指定消费哪个topic的消息以及自己的消费组id(groupId)。

在这里插入图片描述

三、调度器Coordinator

  消费者想要拉取数据,首先必须要加入到一个组中,成为消费组中的一员,同样道理,如果消费者出现了问题,也应该从消费者组中剥离。而这种加入组和退出组的处理,都应该由专门的管理组件进行处理,这个组件在kafka中,我们称之为消费者组调度器(Group Coordinator)。Group Coordinator是Broker上的一个组件,用于管理和调度消费者组的成员、状态、分区分配、偏移量等信息。每个Broker都有一个Group Coordinator对象,负责管理多个消费者组,但每个消费者组只有一个Group Coordinator。

在这里插入图片描述

四、消费者分配策略

4.1、引言

消费者想要拉取主题分区的数据,首先必须要加入到一个组中

在这里插入图片描述
  但是一个组中有多个消费者的话,那么每一个消费者该如何消费呢,是不是像图中一样的消费策略呢?如果是的话,那假设消费者组中只有2个消费者或有4个消费者,和分区的数量不匹配,怎么办?所以介绍一下Kafka中基本的消费者组中的消费者和分区之间的分配规则:

  1. 为了避免数据被重复消费,所以主题一个分区的数据只能被组中的一个消费者消费,但是反过来,一个消费者是可以消费多个分区数据的。
    在这里插入图片描述
  2. 消费者组中的消费者数量最好不要超出主题分区的数据(资源充裕另说哈),就会导致多出的消费者是无法消费数据的,造成了资源的浪费。
    在这里插入图片描述
      消费者中的每个消费者到底消费哪一个主题分区,这个分配策略其实是由消费者的Leader决定的,这个Leader我们称之为群主。群主是多个消费者中,第一个加入组中的消费者,其他消费者我们称之为Follower,称呼上有点类似与分区的Leader和Follower。

在这里插入图片描述
  当消费者加入群组的时候,会发送一个JoinGroup请求。群主负责给每一个消费者分配分区。每个消费者只知道自己的分配信息,只有群主知道群组内所有消费者的分配信息

4.2、分配基本流程

4.3、分配策略

4.3.1、轮询分配策略

4.3.2、轮询分配策略

五、消费偏移量

  偏移量offset是消费者消费数据的一个非常重要的属性。默认情况下,消费者如果不指定消费主题数据的偏移量,那么消费者启动消费时,无论当前主题之前存储了多少历史数据,消费者只能从连接成功后当前主题最新的数据偏移位置读取,而无法读取之前的任何数据,如果想要获取之前的数据,就需要设定配置参数或指定数据偏移量。

5.1、起始偏移量

在消费者的配置中,我们可以增加偏移量相关参数auto.offset.reset,用于从最开始获取主题数据:

public class KafkaConsumerTest {public static void main(String[] args) {// TODO 创建消费者配置参数集合Map<String, Object> paramMap = new HashMap<>();paramMap.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");paramMap.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");paramMap.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());paramMap.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());paramMap.put(ConsumerConfig.GROUP_ID_CONFIG, "test");// TODO 通过配置,创建消费者对象KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(paramMap);// TODO 订阅主题consumer.subscribe(Arrays.asList("test"));while ( true ) {// TODO 消费数据final ConsumerRecords<String, String> poll = consumer.poll(Duration.ofMillis(100));// TODO 遍历数据for (ConsumerRecord<String, String> record : poll) {System.out.println( record );}}}
}

auto.offset.reset有三种取值:

1、earliest
对于同一个消费者组,从头开始消费。就是说如果这个topic有历史消息存在,现在新启动了一个消费者组,且auto.offset.reset=earliest,那将会从头开始消费(未提交偏移量的场合)。

在这里插入图片描述
2、latest
对于同一个消费者组,消费者只能消费到连接topic后,新产生的数据(未提交偏移量的场合)。

在这里插入图片描述
3、none:生产环境不使用。

5.2、指定偏移量消费

除了上一节所讲的从最开始的偏移量或最后的偏移量读取数据以外,Kafka还支持从指定偏移量的位置开始消费数据:

public class KafkaConsumerOffsetTest {public static void main(String[] args) {Map<String, Object> paramMap = new HashMap<>();paramMap.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");paramMap.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());paramMap.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());paramMap.put(ConsumerConfig.GROUP_ID_CONFIG, "test");KafkaConsumer<String, String> c = new KafkaConsumer<String, String>(paramMap);// TODO 订阅主题c.subscribe(Collections.singletonList("test"));// TODO 拉取数据,获取基本集群信息c.poll(Duration.ofMillis(100));// TODO 根据集群的基本信息配置需要消费的主题及偏移量final Set<TopicPartition> assignment = c.assignment();for (TopicPartition topicPartition : assignment) {if ( topicPartition.topic().equals("test") ) {c.seek(topicPartition, 0);}}// TODO 拉取数据while (true) {final ConsumerRecords<String, String> poll = c.poll(Duration.ofMillis(100));for (ConsumerRecord<String, String> record : poll) {System.out.println( record.value() );}}}
}

5.3、偏移量提交

  生产环境中,消费者可能因为某些原因或故障重新启动消费,那么如果不知道之前消费数据的位置,重启后再消费,就可能重复消费(earliest)或漏消费(latest)。所以Kafka提供了保存消费者偏移量的功能,而这个功能需要由消费者进行提交操作。这样消费者重启后就可以根据之前提交的偏移量进行消费了。

注意:一旦消费者提交了偏移量,那么kafka会优先使用提交的偏移量进行消费。此时,auto.offset.reset参数是不起作用的。

5.3.1、自动提交

  所谓的自动提交就是消费者消费完数据后,无需告知kafka当前消费数据的偏移量,而是由消费者客户端API周期性地将消费的偏移量提交到Kafka中。这个周期默认为5000ms,可以通过配置进行修改。

public class KafkaConsumerCommitAutoTest {public static void main(String[] args) {// TODO 创建消费者配置参数集合Map<String, Object> paramMap = new HashMap<>();paramMap.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");// TODO 启用自动提交消费偏移量,默认取值为trueparamMap.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true);// TODO 设置自动提交offset的时间周期为1000ms,默认5000msparamMap.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, 1000);paramMap.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());paramMap.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());paramMap.put(ConsumerConfig.GROUP_ID_CONFIG, "test");// TODO 通过配置,创建消费者对象KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(paramMap);// TODO 订阅主题consumer.subscribe(Arrays.asList("test"));while ( true ) {// TODO 消费数据final ConsumerRecords<String, String> poll = consumer.poll(Duration.ofMillis(100));// TODO 遍历数据for (ConsumerRecord<String, String> record : poll) {System.out.println( record );}}}
}

5.3.2、手动提交

  基于时间周期的偏移量提交,是我们无法控制的,一旦参数设置的不合理,或单位时间内数据量消费的很多,却没有来及的自动提交,那么数据就会重复消费。所以Kafka也支持消费偏移量的手动提交,也就是说当消费者消费完数据后,自行通过API进行提交。不过为了考虑效率和安全,kafka同时提供了异步提交和同步提交两种方式供我们选择。注意:需要禁用自动提交ENABLE_AUTO_COMMIT_CONFIG=false,才能开启手动提交:

1、异步提交

  向Kafka发送偏移量offset提交请求后,就可以直接消费下一批数据,因为无需等待kafka的提交确认,所以无法知道当前的偏移量一定提交成功,安全性比较低,但相对,消费性能会提高

public class KafkaConsumerCommitASyncTest {public static void main(String[] args) {// TODO 创建消费者配置参数集合Map<String, Object> paramMap = new HashMap<>();paramMap.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");// TODO 禁用自动提交消费偏移量,默认取值为trueparamMap.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);paramMap.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());paramMap.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());paramMap.put(ConsumerConfig.GROUP_ID_CONFIG, "test");// TODO 通过配置,创建消费者对象KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(paramMap);// TODO 订阅主题consumer.subscribe(Arrays.asList("test"));while ( true ) {// TODO 消费数据final ConsumerRecords<String, String> poll = consumer.poll(Duration.ofMillis(100));// TODO 遍历处理数据for (ConsumerRecord<String, String> record : poll) {System.out.println( record );}// TODO 异步提交偏移量//     此处需要注意,需要在拉取数据完成处理后再提交//     否则提前提交了,但数据处理失败,下一次消费数据就拉取不到了consumer.commitAsync();}}
}

2、同步提交

  必须等待Kafka完成offset提交请求的响应后,才可以消费下一批数据,一旦提交失败,会进行重试处理,尽可能保证偏移量提交成功,但是依然可能因为意外情况导致提交请求失败。此种方式消费效率比较低,但是安全性高。

5.4、偏移量的保存

  由于消费者在消费消息的时候可能会由于各种原因而断开消费,当重新启动消费者时我们需要让它接着上次消费的位置offset继续消费,因此消费者需要实时的记录自己以及消费的位置。0.90版本之前,这个信息是记录在zookeeper内的,在0.90之后的版本,offset保存在_consumer_offsets这个topic内。

  每个consumer会定期将自己消费分区的offset提交给_consumer_offsets,提交过去的时候,key是consumerGroupId+topic+分区号

在这里插入图片描述

六、消费者事务

6.1、消费者事务原理

无论偏移量使用自动提交还是手动提交,特殊场景中数据都有可能会出现重复消费

在这里插入图片描述
如果提前提交偏移量,再处理业务,又可能出现数据丢失的情况:

在这里插入图片描述
  对于单独的Consumer来讲,事务保证会比较弱,尤其是无法保证提交的信息被精确消费,主要原因就是消费者可以通过偏移量访问信息,而不同的数据文件生命周期不同,同一事务的信息可能会因为重启导致被删除的情况。所以一般情况下,想要完成kafka消费者端的事务处理,需要将数据消费过程偏移量提交过程进行原子性绑定,也就是说数据处理完了,必须要保证偏移量正确提交,才可以做下一步的操作,如果偏移量提交失败,那么数据就恢复成处理之前的效果。

  对于生产者事务而言,消费者消费的数据也会受到限制。默认情况下,消费者只能消费到生产者已提交的数据。如果想要消费到未提交的数据,需要更高消费事务隔离级别。

6.2、示例代码

public class KafkaConsumerTransactionTest {public static void main(String[] args) {Map<String, Object> paramMap = new HashMap<>();paramMap.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");paramMap.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());paramMap.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());// TODO 隔离级别:已提交读,读取已经提交事务成功的数据(默认)//paramMap.put(ConsumerConfig.ISOLATION_LEVEL_CONFIG, "read_committed");// TODO 隔离级别:未提交读,读取已经提交事务成功和未提交事务成功的数据paramMap.put(ConsumerConfig.ISOLATION_LEVEL_CONFIG, "read_uncommitted");paramMap.put(ConsumerConfig.GROUP_ID_CONFIG, "test");KafkaConsumer<String, String> c = new KafkaConsumer<String, String>(paramMap);c.subscribe(Collections.singletonList("test"));while (true) {final ConsumerRecords<String, String> poll = c.poll(Duration.ofMillis(100));for (ConsumerRecord<String, String> record : poll) {System.out.println( record.value() );}}}
}

 
总结

  1. 消费者想要拉取主题分区的数据,首先必须要加入到一个组中。
  2. 一个生产者可以向多个topic推送数据,可以向一个topic中的多个分区推送数据。
  3. 一个消费者组可以订阅多个topic,一个消费者可以订阅多个topic,一个消费者可以消费多个分区数据,一个分区可以被多个消费者组消费,但是一个分区只能被消费者组中的一个消费者消费。

相关文章:

kafka进阶_3.消费消息

文章目录 一、消费消息概览1.1、消费示例代码1.2、消费过程 二、消费者组2.1、push & pull2.2、消费者组 三、调度器Coordinator四、消费者分配策略4.1、引言4.2、分配基本流程4.3、分配策略4.3.1、轮询分配策略4.3.2、轮询分配策略 五、消费偏移量5.1、起始偏移量5.2、指定…...

预测未来 | MATLAB实现Transformer时间序列预测未来

预测未来 | MATLAB实现Transformer时间序列预测未来 预测效果 基本介绍 1.Matlab实现Transformer时间序列预测未来&#xff1b; 2.运行环境Matlab2023b及以上&#xff0c;data为数据集&#xff0c;单变量时间序列预测&#xff1b; 3.递归预测未来数据&#xff0c;可以控制预…...

VirtualBox7.0.6安装配置

VirtualBox7.0.6安装配置 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 文章目录 VirtualBox7.0.6安装配置1.安装虚拟机1.1安装虚拟机的必要条件1.1.1开启虚拟化1.1.1.1检查虚拟化是否开启1.1.1.2 开启虚拟化 1.2 安装虚拟机1.1创建…...

Spring Boot英语知识分享网站:技术与实践

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…...

HarmonyOS4+NEXT星河版入门与项目实战(22)------动画(属性动画与显示动画)

文章目录 1、属性动画图解2、案例实现-小鱼移动游戏1、代码实现2、代码解释3、资源图片4、实现效果3、显示动画4、案例修改-显示动画5、总结1、属性动画图解 这里我们用一张完整的图来汇整属性动画的用法格式和使用的主要属性范围,如下所示: 2、案例实现-小鱼移动游戏 1、代…...

AI赋能公共服务转型升级 | 第十届中国行业互联网大会暨腾讯云TVP行业大使三周年庆典公共服务专场圆满举办!

引言 党的二十大报告把“基本公共服务实现均等化”作为 2035 年我国发展的总体目标之一&#xff0c;强调要“健全基本公共服务体系&#xff0c;提高公共服务水平”。AI 作为新质生产力的核心驱动力之一&#xff0c;正在公共服务领域发挥着越来越重要的作用。 2024 年 10 月 2…...

网络基础 - 地址篇

一、IP 地址 IP 协议有两个版本&#xff0c;IPv4 和 IPv6IP 地址(IPv4 地址)是一个 4 字节&#xff0c;32 位的正整数&#xff0c;通常使用 “点分十进制” 的字符串进行表示&#xff0c;例如 192.168.0.1&#xff0c;用点分割的每一个数字表示一个字节&#xff0c;范围是 0 ~…...

chrome允许http网站打开摄像头和麦克风

第一步 chrome://flags/#unsafely-treat-insecure-origin-as-secure 第二步 填入网址&#xff0c;点击启用 第三步 重启 Chrome&#xff1a;设置完成后&#xff0c;点击页面底部的 “Relaunch” 按钮&#xff0c;重新启动 Chrome 浏览器&#xff0c;使更改生效。...

uniapp前端开发,基于vue3,element plus组件库,以及axios通讯

简介 UniApp 是一个基于 Vue.js 的跨平台开发框架&#xff0c;旨在通过一次开发、编译后运行在多个平台上&#xff0c;如 iOS、Android、H5、以及小程序&#xff08;微信小程序、支付宝小程序、百度小程序等&#xff09;等。UniApp 为开发者提供了统一的开发体验&#xff0c;使…...

STM32-- 串口发送数据

while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);&#xff1f;&#xff1f; 答&#xff1a; 这行代码&#xff1a; while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) RESET);的作用是等待串口 USART2 的发送数据寄存器&#xff08;TXE&#xff0c;Transmit Dat…...

网络安全提示

如果您是企业主或 IT 经理&#xff0c;您应该知道计算机安全的重要性。从保护密码安全的基础知识到网络钓鱼、恶意软件等的危险&#xff0c;本文将为您提供您需要了解的有关网络安全的信息。 每年&#xff0c;互联网都变得越来越大&#xff0c;这意味着我们为黑客和网络犯罪分…...

【计算机网络】多路转接之epoll

epoll也是一种linux中的多路转接方案(epoll也是只负责IO过程中的"等") 一、epoll相关接口的使用 1.epoll_create int epoll_create(int size); ​功能&#xff1a;创建一个epoll模型 ① int size&#xff1a;没意义了 >0就行 返回值&#xff1a;返回一个文件…...

nextjs+nestjs+prisma写todolist全栈项目

技术栈 nextjsnestjsprisma所学知识 Nextjs组件渲染,状态,路由docker启动Mysql容器prisma操作Mysql(CRUD)允许跨域请求APITanStack Query异步状态管理fetch api服务器组件预请求数据nestjs 管道和异常处理检测id是否正整数Docker启动Mysql容器 compose.yml name: todoLis…...

重构代码之将双向关联改为单向关联

在代码重构中&#xff0c;双向关联改为单向关联是指将原本双向关联转变为单向关联。这种重构方式有助于简化对象模型和提高代码的可维护性&#xff0c;减少不必要的耦合。下面是对这个重构技巧的详细讲解。 一、为什么需要将双向关联改为单向关联&#xff1f; 减少耦合&#…...

Linux介绍与安装指南:从入门到精通

1. Linux简介 1.1 什么是Linux&#xff1f; Linux是一种基于Unix的操作系统&#xff0c;由Linus Torvalds于1991年首次发布。Linux的核心&#xff08;Kernel&#xff09;是开源的&#xff0c;允许任何人自由使用、修改和分发。Linux操作系统通常包括Linux内核、GNU工具集、图…...

深度学习中的正则化模型是什么意思?

一、定义 在深度学习中&#xff0c;正则化是一种用于防止过拟合的技术。过拟合是指模型在训练数据上表现非常好&#xff0c;但在新的、未见过的数据&#xff08;测试数据&#xff09;上表现很差的情况。正则化模型就是通过在损失函数中添加额外的项来约束模型的复杂度&#xf…...

rabbitMq两种消费应答失败处理方式

在rabbitMq消费端&#xff0c;有三种应答模式&#xff1a; none&#xff1a;不处理。即消息投递给消费者后立刻 ack 消息会立刻从MQ删除。非常不安全&#xff0c;不建议使用 manual&#xff1a;手动模式。需要自己在业务代码中调用api&#xff0c;发送 ack 或 reject&#xff…...

windows C#-使用反射访问特性

你可以定义自定义特性并将其放入源代码中这一事实&#xff0c;在没有检索该信息并对其进行操作的方法的情况下将没有任何价值。 通过使用反射&#xff0c;可以检索通过自定义特性定义的信息。 主要方法是 GetCustomAttributes&#xff0c;它返回对象数组&#xff0c;这些对象在…...

java中链表的数据结构的理解

在 Java 中&#xff0c;链表是一种常见的数据结构&#xff0c;可以通过类的方式实现自定义链表。以下是关于 Java 中链表的数据结构和实现方式的详细介绍。 1. 自定义链表结构 Java 中链表通常由一个节点类 (ListNode) 和可能的链表操作类构成。 节点类 (ListNode) 这是链表…...

ctfshow

1,web153 大小写绕过失败 使用.user.ini 来构造后⻔ php.ini是php的⼀个全局配置⽂件&#xff0c;对整个web服务起作⽤&#xff1b;⽽.user.ini和.htaccess⼀样是⽬录的配置⽂件&#xff0c;.user.ini就是⽤户⾃定义的⼀个php.ini&#xff0c;我们可以利⽤这个⽂件来构造后⻔和…...

【AI绘画】Midjourney进阶:色调详解(下)

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AI绘画 | Midjourney 文章目录 &#x1f4af;前言&#x1f4af;Midjourney中的色彩控制为什么要控制色彩&#xff1f;为什么要在Midjourney中控制色彩&#xff1f; &#x1f4af;色调纯色调灰色调暗色调 &#x1f4af…...

lanqiaoOJ 3747:繁忙的精神疗养院 ← STL queue

【题目来源】https://www.lanqiao.cn/problems/3747/learning/【题目描述】 心灵之园是一家知名的精神疗养院&#xff0c;为了提供更优质的服务&#xff0c;他们专门设立了一个 VIP 诊室和一个普通诊室。VIP 诊室主要接待特殊需求的高级会员&#xff0c;而普通诊室则服务所有的…...

Local Changes不展示,DevEco Studio的git窗口中没有Local Changes

DevEco Studio的git窗口中&#xff0c;没有Local Changes&#xff0c;怎么设置可以调出&#xff1f; 进入File-->Settings-->Version Control&#xff0c;将Use non-modal commit interface前的勾选框取消勾选&#xff0c;点击OK即可在打开git窗口&#xff0c;就可以看到…...

探索Python项目模板化的新纪元 —— Copier库揭秘

文章目录 **探索Python项目模板化的新纪元 —— Copier库揭秘**1. 背景介绍&#xff1a;为何Copier成为Python开发者的新宠&#xff1f;2. Copier究竟是什么&#xff1f;3. 如何安装Copier&#xff1f;4. 简单库函数使用方法创建模板从Git URL创建项目使用快捷方式动态文件生成…...

导入100道注会cpa题的方法,导入试题,自己刷题

一、问题描述 复习备考的小伙伴们&#xff0c;往往希望能够利用零碎的时间和手上的试题&#xff0c;来复习和备考 用一个能够导入自己试题的刷题工具&#xff0c;既能加强练习又能利用好零碎时间&#xff0c;是一个不错的解决方案 目前市面上刷题工具存下这些问题 1、要收费…...

使用NAS开启无纸化办公,Docker部署开源文档管理系统『Paperless-ngx』

使用NAS开启无纸化办公&#xff0c;Docker部署开源文档管理系统『Paperless-ngx』 哈喽小伙伴们好&#xff0c;我是Stark-C~ 对于文案类的办公场景来说&#xff0c;手头堆放最多的可能就是各种文档文件&#xff0c;以及各种用过的打印废纸。 这么多年来&#xff0c;不管是领…...

docker安装mysql

1.拉取mysql镜像 docker pull mysql:5.7 2.启动mysql容器 docker run -d -e MYSQL_ROOT_PASSWORD123456 -e MYSQL_TCP_PORT3307 -p 3307:3307 -v /SDXL/wjz/docker_mysql_log:/var/log/mysql -v /SDXL/wjz/docker_mysql_data:/var/lib/mysql -v /SDXL/wjz/docker_mysql_conf:/e…...

9、深入剖析PyTorch的nn.Sequential及ModuleList源码

文章目录 1. train&eval2. 求导数3. 参数更新4. ModuleList,Sequential5. Parameter&Parameter_List&ParmeterDict 1. train&eval train 模式&#xff1a;表示的是神经网络的训练模式&#xff0c;能够进行样本学习&#xff0c;通过样本来更新权重weighteval 模…...

idea初始化设置

下载idea&#xff1a; https://www.jetbrains.com/idea/ 安装idea 安装插件&#xff1a; Rainbow BracketsLombokMybatisXSonarLintMaven HelperCodeGeeX&#xff08;国内AI插件可用&#xff09; 设置idea注释模板&#xff1a; 设置代码注释模板&#xff1a; https://blo…...

【C/C++】内存管理详解:从new/delete到智能指针的全面解析

文章目录 更多文章C/C中的传统内存管理方式new和delete运算符malloc和free函数传统内存管理的弊端 智能指针的崛起智能指针的定义与作用C11引入的标准智能指针 详解C标准智能指针std::unique_ptr特点使用方法适用场景 std::shared_ptr特点使用方法适用场景 std::weak_ptr特点使…...

Vue.Draggable使用nested-with-vmodel进行拖拽

Vue.Draggable使用nested-with-vmodel进行拖拽 1. 介绍 ‌draggable‌是一个基于Sortable.js的Vue组件&#xff0c;用于实现拖拽功能。它支持触摸设备、拖拽和选择文本、智能滚动、不同列表之间的拖拽等功能&#xff0c;并且与Vue的视图模型同步刷新&#xff0c;兼容Vue2的过…...

MySQL 中的乐观锁与悲观锁

文章目录 MySQL 中的乐观锁与悲观锁一、引言二、乐观锁&#xff08;一&#xff09;原理&#xff08;二&#xff09;应用场景&#xff08;三&#xff09;示例代码 三、悲观锁&#xff08;一&#xff09;原理&#xff08;二&#xff09;应用场景&#xff08;三&#xff09;示例代…...

面试题分享(一)

实习的项目 成员规模 用到过哪些设计模式&#xff1f; 策略、单例、工厂、代理 责任链模式了解吗&#xff1f; 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;目的是为了避免请求的发送者与接收者之间的耦合关系。通…...

用天翼云搭建一个HivisionIDPhoto证件照处理网站

世人不必记我&#xff0c;我不记世人。 HivisionIDPhoto证件照处理网站 世人不必记我&#xff0c;我不记世人。项目地址项目搭建与修改前端后端遇到的坑 成果图 前段时间工作需要频繁处理证件照&#xff0c;当时同事推荐一个证件照小程序&#xff08;要看广告&#xff09;&…...

Conda环境迁移到内网

文章目录 一、conda是什么&#xff1f; conda环境迁移 二、迁移方法 1.docker方式 2.conda包方式 3.conda指定目录创建环境 4.pip方式 5.单个包安装 总结 前言 搞Python&#xff0c;使用conda是避免不了的&#xff0c;利用conda可以方便的管理多个不同的虚拟环境&…...

React Hooks中use的细节

文档 useState useState如果是以函数作为参数&#xff0c;那要求是一个纯函数&#xff0c;不接受任何参数&#xff0c;同时需要一个任意类型的返回值作为初始值。 useState可以传入任何类型的参数作为初始值&#xff0c;当以一个函数作为参数进行传入的时候需要注意&#xff…...

Android 16 开发者预览版抢先使用

Android 16 开发者预览版 获取 Android 16在 Google Pixel 设备上获取 Android 16设置 Android 模拟器 设置 Android 16 SDK获取 Android Studio安装 SDK更新应用的 build 配置 获取 Android 16 你可以通过以下任一方式获取 Android 16 在 Google Pixel 设备上获取 Android 1…...

蓝桥杯c++算法秒杀【6】之动态规划【上】(数字三角形、砝码称重(背包问题)、括号序列、组合数问题:::非常典型的必刷例题!!!)

下将以括号序列、组合数问题超级吧难的题为例子讲解动态规划 别忘了请点个赞收藏关注支持一下博主喵&#xff01;&#xff01;&#xff01;! ! ! ! &#xff01; 关注博主&#xff0c;更多蓝桥杯nice题目静待更新:) 动态规划 一、数字三角形 【问题描述】 上图给出了…...

c#:winform引入bartender

1、vs新建项目 ①选择Windows窗体应用&#xff08;.NET Framework&#xff09; 2、将bartender引入vs中 ①找到bartender的安装目录&#xff0c;复制Seagull.BarTender.Print.dll文件 ②粘贴到项目->bin->Debug文件&#xff0c;并可创建Model文件夹&#xff1a;为了存放…...

Zabbix 模板翻译自动化教程

在企业 IT 运维管理中&#xff0c;Zabbix 作为一款强大的开源监控平台被广泛应用。而 Zabbix 模板作为监控配置的重要组成部分&#xff0c;用来定义监控项、触发器、图形等。随着国际化的需求增加&#xff0c;Zabbix 模板的翻译工作变得日益重要&#xff0c;特别是在需要为不同…...

HarmonyOS开发:DevEco Studio的Beta3(5.0.5.200)新增和增强特性

新增特性 DevEco Studio支持开发API 13工程。DevEco Profiler Frame模板新增Lost Frames和Hitch Time泳道&#xff0c;用于识别和优化卡顿和丢帧现象。具体请参考Frame分析。hvigor-config.json5中properties下新增ohos.arkCompile.noEmitJs字段&#xff0c;用于指定ArkTS编译…...

macOS安装nvm node

macOS安装nvm macOS安装nvm创建 nvm 工作目录配置环境变量使用 nvm查看可用的 Node.js 版本安装特定版本 macOS安装nvm brew install nvm创建 nvm 工作目录 mkdir ~/.nvm配置环境变量 vim ~/.zshrc# nvm export NVM_DIR"$HOME/.nvm" [ -s "/opt/homebrew/opt…...

SpringBoot 集成MQTT实现消息订阅

1、引入依赖 <!--MQTT start--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-integration</artifactId></dependency><dependency><groupId>org.springframework.integrat…...

VM+Ubuntu18.04+XSHELL+VSCode环境配置

前段时间换了新电脑&#xff0c;准备安装Linux学习环境&#xff1a;VM虚拟机、Ubuntu18.04操作系统、XSHELL、XFTP远程连接软件、VSCode编辑器等&#xff0c;打算把安装过程记录一下。 1. 虚拟机介绍 为什么要用虚拟机&#xff1f; 想学习Linux操作系统&#xff0c;一般有3种…...

C#上机练习66-70

66.数组x中存有20个四位整数&#xff0c;请编制函数&#xff0c;求出正整数的个数tn。以及各位数字之和是偶数的数的个数tc,以及满足条件的这些数的算术平均ta.&#xff0c;将tn&#xff0c;tc&#xff0c;ta在控制台输出。 67.数组x中存有20个四位整数&#xff0c;请编制函数…...

pip 与当前python环境版本不匹配, pyenv, pipenv, conda

目录 pip 与当前python环境不匹配解决pip版本不一致 CondaPyenv pip 与当前python环境不匹配 电脑中安装了多个python虚拟环境, 有anaconda创建的虚拟环境,也有pyenv创建的虚拟环境,但是环境变量配置的是anaconda的路径 从而导致在vscode中选择的python版本是3.8.10,而pip却是…...

HAProxy面试题及参考答案(精选80道面试题)

目录 什么是 HAProxy? HAProxy 主要有哪些功能? HAProxy 的关键特性有哪些? HAProxy 的主要功能是什么? HAProxy 的作用是什么? 解释 HAProxy 在网络架构中的作用。 HAProxy 与负载均衡器之间的关系是什么? HAProxy 是如何实现负载均衡的? 阐述 HAProxy 的四层…...

ElasticSearch为什么不能在query阶段直接返回_id,从而避免fetch?

整理自Github的一个issue,也正好解答了我的疑惑 https://github.com/elastic/elasticsearch/issues/17159 提问 是否可以避免搜索的fetch阶段并仅返回文档ID&#xff1f;查询阶段结束时是否有_id&#xff0c;这样当我只需要_id时&#xff0c;fetch就多余了&#xff1f;可以通过…...

任意文件读取漏洞(CVE-2024-7928)修复

验证CVE-2024-7928问题是否存在可以使用如下方法&#xff1a; https://域名/index/ajax/lang?lang..//..//目录名/文件名&#xff08;不带后缀&#xff09; 目录名是该项目的一个目录&#xff0c;这里目录位置为nginx设置站点目录为基准&#xff0c;网上两层目录。 文件名…...

07 初始 Oracle 优化器

查询优化器&#xff0c;简称优化器&#xff0c;是数据库最核心的组件之一。我们在这个系列的第一篇文章中已经给大家介绍了&#xff0c;优化器会参与到SQL语句的解析过程中&#xff0c;用来生成SQL语句的执行计划&#xff0c;直接决定SQL语句执行性能的优劣。 什么是执行计划 …...