关于SpringBoot集成Kafka

关于Kafka

Apache Kafka 是一个分布式流处理平台,广泛用于构建实时数据管道和流应用。它能够处理大量的数据流,具有高吞吐量、可持久化存储、容错性和扩展性等特性。

Kafka一般用作实时数据流处理、消息队列、事件架构驱动等

Kafka的整体架构

  • ZooKeeper:

位于架构的顶部,负责管理和协调 Kafka 集群的各种元数据,包括集群配置、主题信息、分区领导者的选举等。

  • Producers (生产者):

Kafka体系中的主要角色之一,它们负责产生消息并将其发送到 Kafka 集群中的相应主题。

  • Brokers (代理/服务器):节点,也就是具体的Kafka实例,集群的组成单元,多个 Broker 组成一个集群。每个 Broker 存储着一部分主题的分区数据。
    • Topics (主题):主题是消息的类别,生产者将消息发布到特定的主题。一个Brokers包含多个topic。
      • Partitions (分区):每个主题可以划分为一个或多个分区,分区是物理上存储消息的地方。一个主题可以有多个分区
        • Leaders and Followers (领导者和跟随者):对于每个分区,有一个 Leader 负责接受所有生产和消费请求,而 Follower 则复制 Leader (图中红色部分)的数据。
        • Segments (段): 分区内部又细分为多个 Segment,每个 Segment 包括一个 .log 文件和其他相关文件,用于消息数据持久化。 
  • Consumers (消费者):

Kafka体系中的另一个主要角色,它们订阅主题并从 Kafka 集群中拉取消息。消费者可以组织成消费者组,同一组内的消费者共享消息。

Kafka的工作流程

  • 消息发布

生产者创建消息并将它们发送到指定的主题。生产者可以选择将消息发送到特定的分区,或者让 Kafka 根据某种策略(如轮询、哈希等)自动选择分区。

  • 消息存储

当消息到达Broker时,它会被追加到指定分区的日志文件末尾。每个分区都是一个独立的日志文件,按照偏移量(Offset)进行索引,确保消息的顺序性。

  • 消息消费

消费者订阅感兴趣的主题,并从指定的分区读取消息。消费者通过维护一个偏移量来跟踪已经处理的消息,确保不会重复消费。

  • 故障恢复

如果Broker发生故障,Kafka会从其他副本中选举一个新的Leader分区来继续提供服务,确保系统的高可用性。 

SpringBoot集成Kafka

引入依赖

在SpringBoot框架下,可以直接通过引入Kafka依

    <!-- Spring Kafka Starter --><dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId></dependency>

yaml配置详解

关于SpringBoot中使用Kafka的配置结构如下:

spring:kafka:bootstrap-servers: localhost:9092  # Kafka整体配置:服务器地址,可以是多个以逗号分隔consumer: #作为消费者的具体配置group-id: my-group # 消费者的组ID,属于同一组的消费者会互相竞争消费消息# …… 消费者其他的配置producer: #作为生产者的具体配置value-serializer: org.apache.kafka.common.serialization.StringSerializer # 值的序列化器#……其他控制生产者的配置

各类参数配置说明:

归属配置项说明默认值作用
全局bootstrap-servers指定Kafka集群的地址,可以是多个地址,用逗号分隔-生产者和消费者通过这些地址与Kafka集群建立连接
消费者consumer.group-id指定消费者的组ID-属于同一组的消费者会互相竞争消费消息,确保每个消息只被组内的一个消费者消费
consumer.auto-offset-reset当没有初始偏移量可用或当前偏移量不再存在时,自动重置偏移量的策略latest决定了在消费者组没有已知偏移量时,从哪里开始读取消息
consumer.key-deserializer指定键的反序列化器org.apache.kafka.common.serialization.ByteArrayDeserializer将从Kafka接收到的字节数据转换为Java对象
consumer.value-deserializer指定值的反序列化器org.apache.kafka.common.serialization.ByteArrayDeserializer将从Kafka接收到的字节数据转换为Java对象
consumer.enable-auto-commit是否启用自动提交偏移量true如果启用,消费者会定期自动提交偏移量,否则需要手动提交
consumer.auto-commit-interval自动提交偏移量的时间间隔(毫秒)5000(5秒)控制自动提交的频率
consumer.max-poll-records单次轮询返回的最大记录数500控制每次轮询从Kafka获取的消息数量
consumer.fetch-min-bytes消费者从Kafka获取数据的最小字节数1如果小于该值,Kafka不会立即返回数据,而是等待更多数据积累
consumer.fetch-max-wait消费者从Kafka获取数据的最大等待时间(毫秒)500控制消费者在没有足够数据时的等待时间
consumer.session-timeout消费者会话超时时间(毫秒)10000(10秒)控制消费者在未发送心跳的情况下,Kafka认为其失效的时间
生产者producer.key-serializer指定键的序列化器org.apache.kafka.common.serialization.ByteArraySerializer将Java对象转换为字节数据,以便发送到Kafka
producer.value-serializer指定值的序列化器org.apache.kafka.common.serialization.ByteArraySerializer将Java对象转换为字节数据,以便发送到Kafka
producer.acks生产者发送消息时的确认模式1控制消息发送的可靠性
producer.retries生产者发送消息失败时的重试次数0控制消息发送失败时的重试机制
producer.batch-size生产者批量发送消息的大小(字节)16384(16KB)控制消息的批量发送,提高性能
producer.linger-ms生产者在发送消息前等待的时间(毫秒),以便收集更多的消息进行批量发送0控制消息的批量发送,提高性能

示例配置

spring:kafka:# 指定Kafka集群的地址,可以是多个地址,用逗号分隔# 生产者和消费者通过这些地址与Kafka集群建立连接bootstrap-servers: localhost:9092consumer:# 指定消费者的组ID# 属于同一组的消费者会互相竞争消费消息,确保每个消息只被组内的一个消费者消费group-id: my-group# 当没有初始偏移量可用或当前偏移量不再存在时,自动重置偏移量的策略# 可选值: earliest, latest, none# earliest: 自动重置为最早的偏移量# latest: 自动重置为最新的偏移量# none: 如果没有找到消费者组的偏移量,则抛出异常auto-offset-reset: earliest# 指定键的反序列化器# 将从Kafka接收到的字节数据转换为Java对象key-deserializer: org.apache.kafka.common.serialization.StringDeserializer# 指定值的反序列化器# 将从Kafka接收到的字节数据转换为Java对象value-deserializer: org.apache.kafka.common.serialization.StringDeserializer# 是否启用自动提交偏移量# 如果启用,消费者会定期自动提交偏移量,否则需要手动提交enable-auto-commit: true# 自动提交偏移量的时间间隔(毫秒)# 控制自动提交的频率auto-commit-interval: 5000# 单次轮询返回的最大记录数# 控制每次轮询从Kafka获取的消息数量max-poll-records: 100# 消费者从Kafka获取数据的最小字节数# 如果小于该值,Kafka不会立即返回数据,而是等待更多数据积累fetch-min-bytes: 1# 消费者从Kafka获取数据的最大等待时间(毫秒)# 控制消费者在没有足够数据时的等待时间fetch-max-wait: 500# 消费者会话超时时间(毫秒)# 控制消费者在未发送心跳的情况下,Kafka认为其失效的时间session-timeout: 10000producer:# 指定键的序列化器# 将Java对象转换为字节数据,以便发送到Kafkakey-serializer: org.apache.kafka.common.serialization.StringSerializer# 指定值的序列化器# 将Java对象转换为字节数据,以便发送到Kafkavalue-serializer: org.apache.kafka.common.serialization.StringSerializer# 生产者发送消息时的确认模式# 可选值: 0, 1, all# 0: 不等待任何确认# 1: 等待leader节点确认# all: 等待所有副本节点确认acks: all# 生产者发送消息失败时的重试次数# 控制消息发送失败时的重试机制retries: 3# 生产者批量发送消息的大小(字节)# 控制消息的批量发送,提高性能batch-size: 16384# 生产者在发送消息前等待的时间(毫秒),以便收集更多的消息进行批量发送# 控制消息的批量发送,提高性能linger-ms: 1

关于消费者的 auto-commit属性:

enable-auto-commit 是Kafka消费者的一个重要配置属性,它决定了消费者是否自动提交偏移量。

如果设置为true,即自动提交:

  • 消费者会定期自动提交偏移量。
  • 提交的频率由 auto-commit-interval 配置项决定,默认为5秒。
  • 消费者在每次轮询后会检查是否需要提交偏移量,如果达到提交间隔时间,则提交当前偏移量。

设置为true的优势主要在于简化开发,如果消费者崩溃,重新启动后可以从上次提交的偏移量继续消费,避免重复消费大量消息。劣势则是自动提交的频率在处理大数据量是会有性能风险。

如果设置为false,即手动提交:

  • 消费者不会自动提交偏移量。
  • 开发者需要手动调用方法来提交偏移量(具体提交方法在下文)
  • 可以在消息处理完成后立即提交偏移量,也可以批量提交。

设置为false的优势在于更为精准的控制,能有效提升性能,开发者可以完全控制何时提交偏移量,确保消息处理的可靠性和一致性。可以根据业务需求选择同步提交或异步提交,具有更强的灵活性。劣势则是如果忘记提交偏移量,可能会导致消息重复消费或丢失。

消费与生成的使用

进行消息监听与消费

消息的监听主要是通过@KafkaListener注解来完成,以下是一个例子:

@Service
public class KafkaConsumer {@Autowiredprivate DataService dataService;@KafkaListener(topics = "my-topic", groupId = "my-group")public void listen(String message) {//如果你的方法参数是一个 String 类型,那么默认情况下,这个参数会被解析为消息的值(Value)log.info("Received Message: {}" , message);dataService.OpData(message); }//如果你想同时获取消息的键(Key)和值(Value),可以使用 ConsumerRecord 对象。ConsumerRecord 包含了消息的所有信息,包括键、值、分区、偏移量等。@KafkaListener(topics = "my-topic")public void listen(ConsumerRecord<String, String> record) {log.info("Received Message Key: " + record.key());log.info("Received Message Value: " + record.value());log.info("Partition: " + record.partition());log.info("Offset: " + record.offset());}}

关于@KafkaListener注解的参数如下:

参数类型说明示例
topicsString[]指定要监听的主题列表。@KafkaListener(topics = "my-topic")
topicPartitionsTopicPartitionOffset[]指定要监听的主题和分区。可以用于更细粒度的控制。@KafkaListener(topicPartitions = @TopicPartition(topic = "my-topic", partitions = { "0", "1" }))
groupIdString指定消费者的组ID。如果在配置文件中已经指定了组ID,这里可以省略。@KafkaListener(topics = "my-topic", groupId = "my-group")
containerFactoryString指定用于创建监听器容器的工厂Bean的名称。通常在配置类中定义。@KafkaListener(topics = "my-topic", containerFactory = "kafkaListenerContainerFactory")
idString指定监听器的唯一标识符。可以在监控和管理中使用。@KafkaListener(topics = "my-topic", id = "myListener")
concurrencyString指定并发消费者线程的数量。@KafkaListener(topics = "my-topic", concurrency = "3")
autoStartupboolean指定监听器是否在应用程序启动时自动启动。@KafkaListener(topics = "my-topic", autoStartup = "false")
propertiesMap<String, String>指定额外的Kafka消费者属性。@KafkaListener(topics = "my-topic", properties = "max.poll.interval.ms:120000")
groupIdPrefixString指定组ID的前缀。实际的组ID将是前缀加上方法名。@KafkaListener(topics = "my-topic", groupIdPrefix = "prefix-")
clientIdPrefixString指定客户端ID的前缀。实际的客户端ID将是前缀加上方法名。@KafkaListener(topics = "my-topic", clientIdPrefix = "client-")
containerPropertiesContainerProperties指定容器的属性。@KafkaListener(topics = "my-topic", containerProperties = @ContainerProperties(ackMode = AckMode.MANUAL))
errorHandlerString指定错误处理器Bean的名称。@KafkaListener(topics = "my-topic", errorHandler = "myErrorHandler")
replyTemplateString指定回复模板Bean的名称。@KafkaListener(topics = "my-topic", replyTemplate = "myReplyTemplate")
replyTopicString指定回复主题。@KafkaListener(topics = "my-topic", replyTopic = "reply-topic")
replyTimeoutlong指定回复超时时间(毫秒)。@KafkaListener(topics = "my-topic", replyTimeout = 5000)
replyHeadersString[]指定要传递的回复头。@KafkaListener(topics = "my-topic", replyHeaders = { "header1", "header2" })
groupIdIsolationLevelIsolationLevel指定隔离级别。@KafkaListener(topics = "my-topic", groupIdIsolationLevel = IsolationLevel.READ_COMMITTED)
containerGroupString指定容器组。@KafkaListener(topics = "my-topic", containerGroup = "group1")

 额外说明一下containerFactory 参数,为了使用 containerFactory 参数,你需要在配置类中定义相应的工厂Bean:


@Configuration
@EnableKafka
public class KafkaConfig {@Beanpublic ConsumerFactory<String, String> consumerFactory() {Map<String, Object> props = new HashMap<>();props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");props.put(ConsumerConfig.GROUP_ID_CONFIG, "my-group");props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);return new DefaultKafkaConsumerFactory<>(props);}@Beanpublic ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();factory.setConsumerFactory(consumerFactory());factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);return factory;}
}

基于使用containerFactory配置一般主要用于手动提交的时候,可以在方法中使用提交参数,如下:

@Service
public class KafkaConsumer {@KafkaListener(topics = "my-topic",containerFactory = "kafkaListenerContainerFactory")public void listen(ConsumerRecord<String, String> record, Acknowledgment acknowledgment){log.info("Received Message: " + record.value());// 处理消息try {// 模拟消息处理Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// 手动提交偏移量 enable-auto-commit为false的话acknowledgment.acknowledge();}
}

消息生产

主要是基于KafkaTemplate进行消息的发送,可以根据需求,先定义生产者的工厂Bean:

@Configuration
public class KafkaProducerConfig {@Beanpublic ProducerFactory<String, String> producerFactory() {Map<String, Object> configProps = new HashMap<>();configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);return new DefaultKafkaProducerFactory<>(configProps);}@Beanpublic KafkaTemplate<String, String> kafkaTemplate() {return new KafkaTemplate<>(producerFactory());}
}

 封装生产者方法:

@Service
public class KafkaProducer {@Autowiredprivate KafkaTemplate<String, String> kafkaTemplate;/*** 发送字符串消息到指定主题** @param topic   主题名称* @param message 消息内容*/public void sendMessage(String topic, String message) {kafkaTemplate.send(topic, message);}/*** 发送带键的字符串消息到指定主题** @param topic   主题名称* @param key     消息键* @param message 消息内容*/public void sendMessageWithKey(String topic, String key, String message) {kafkaTemplate.send(topic, key, message);}/*** 异步发送消息并处理回调** @param topic   主题名称* @param message 消息内容* @param callback 回调函数*/public void sendAsyncMessage(String topic, String message, KafkaCallback<String, String> callback) {kafkaTemplate.send(topic, message).addCallback(callback);}/*** 异步发送带键的消息并处理回调** @param topic   主题名称* @param key     消息键* @param message 消息内容* @param callback 回调函数*/public void sendAsyncMessageWithKey(String topic, String key, String message, KafkaCallback<String, String> callback) {kafkaTemplate.send(topic, key, message).addCallback(callback);}
}

为了支持异步发送消息并处理回调,定义回调不同的接口:

public interface KafkaCallback<K, V> extends ListenableFutureCallback<SendResult<K, V>> {@Overridedefault void onSuccess(SendResult<K, V> result) {//回调处理}@Overridedefault void onFailure(Throwable ex) {//处理}
}

 直接使用

@RestController
@RequestMapping("/kafka")
public class KafkaController {@Autowiredprivate KafkaProducerService kafkaProducerService;@PostMapping("/send")public String sendMessage(@RequestBody String message) {kafkaProducerService.sendMessage("my-topic", message);return "Message sent: " + message;}@PostMapping("/send-with-key")public String sendMessageWithKey(@RequestBody String message) {kafkaProducerService.sendMessageWithKey("my-topic", "key1", message);return "Message with key sent: " + message;}@PostMapping("/send-async")public String sendAsyncMessage(@RequestBody String message) {kafkaProducerService.sendAsyncMessage("my-topic", message, new KafkaCallback<String, String>());return "Async message sent: " + message;}@PostMapping("/send-async-with-key")public String sendAsyncMessageWithKey(@RequestBody String message) {kafkaProducerService.sendAsyncMessageWithKey("my-topic", "key1", message, new KafkaCallback<String, String>());return "Async message with key sent: " + message;}
}

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

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

相关文章

在Unity中实现物体动画的完整流程

在Unity中&#xff0c;动画是游戏开发中不可或缺的一部分。无论是2D还是3D游戏&#xff0c;动画都能为游戏增添生动的视觉效果。本文将详细介绍如何在Unity中为物体添加动画&#xff0c;包括资源的准备、播放组件的添加、动画控制器的创建以及动画片段的制作与调度。 1. 准备动…

自定义协议

1. 问题引入 问题&#xff1a;TCP是面向字节流的&#xff08;TCP不关心发送的数据是消息、文件还是其他任何类型的数据。它简单地将所有数据视为一个字节序列&#xff0c;即字节流。这意味着TCP不会对发送的数据进行任何特定的边界划分&#xff0c;它只是确保数据的顺序和完整…

Spring Boot 3.4.0 发行:革新与突破的里程碑

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

android 11添加切换分屏功能

引言 自Android 7开始官方就支持分屏显示,但没有切换分屏的功能,即交换上下屏幕。直到Android 13开始才支持切换分屏,操作方式是:分屏模式下双击中间分割线就会交换上下屏位置。本文的目的就是在Android 11上实现切换分屏的功能。 下图是Android13切换分屏演示 切换分屏…

PyTorch基础05_模型的保存和加载

目录 一、模型定义组件——重构线性回归 二、模型的加载和保存 2、序列化保存对象和加载 3、保存模型参数 一、模型定义组件——重构线性回归 回顾之前的手动构建线性回归案例&#xff1a; 1.构建数据集&#xff1b;2.加载数据集(数据集转换为迭代器)&#xff1b;3.参数初…

JavaScript核心语法(3)

前两篇文章大概把JavaScript的基础语法讲了一下&#xff0c;这篇文章主要讲讲ES6的核心语法。ES6的核心语法说实话其实有点多&#xff0c;我重点挑一些经常在项目中用到的来讲&#xff0c;其他一些我没怎么见过的就不讲了。 目录 1.变量和常量 变量&#xff08;let 和 var&a…

爬虫开发(5)如何写一个CSDN热门榜爬虫小程序

笔者 綦枫Maple 的其他作品&#xff0c;欢迎点击查阅哦~&#xff1a; &#x1f4da;Jmeter性能测试大全&#xff1a;Jmeter性能测试大全系列教程&#xff01;持续更新中&#xff01; &#x1f4da;UI自动化测试系列&#xff1a; SeleniumJava自动化测试系列教程❤ &#x1f4da…

NIO三大组件

现在互联网环境下&#xff0c;分布式系统大相径庭&#xff0c;而分布式系统的根基在于网络编程&#xff0c;而netty恰恰是java领域的网络编程的王者&#xff0c;如果要致力于并发高性能的服务器程序、高性能的客户端程序&#xff0c;必须掌握netty网络编程。 NIO基础 NIO是从ja…

34 基于单片机的指纹打卡系统

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STC89C52RC&#xff0c;采用两个按键替代指纹&#xff0c;一个按键按下&#xff0c;LCD12864显示比对成功&#xff0c;则 采用ULN2003驱动步进电机转动&#xff0c;表示开门&#xff0c;另一个…

李宏毅机器学习课程知识点摘要(14-18集)

线性回归&#xff0c;逻辑回归&#xff08;线性回归sigmoid&#xff09;&#xff0c;神经网络 linear regression &#xff0c; logistic regression &#xff0c; neutral network 里面的偏导的相量有几百万维&#xff0c;这就是neutral network的不同&#xff0c;他是…

文件上传upload-labs-docker通关

&#xff08;图片加载不出&#xff0c;说明被和谐了&#xff09; 项目一&#xff1a; sqlsec/ggctf-upload - Docker Image | Docker Hub 学习过程中,可以对照源码进行白盒分析. 补充&#xff1a;环境搭建在Linux虚拟机上的同时&#xff0c;以另一台Windows虚拟机进行测试最…

【Android】静态广播接收不到问题分析思路

参考资料&#xff1a; Android 静态广播注册流程(广播2)-CSDN博客 Android广播发送流程(广播3)_android 发送广播-CSDN博客 https://zhuanlan.zhihu.com/p/347227068 在Android中&#xff0c;静态广播如果静态广播不能接收&#xff0c;我们可以从整个流程中去分析&#xff…

2024 APMCM亚太数学建模C题 - 宠物行业及相关产业的发展分析和策略(详细解题思路)

在当下&#xff0c; 日益发展的时代&#xff0c;宠物的数量应该均为稳步上升&#xff0c;在美国出现了下降的趋势&#xff0c; 中国 2019-2020 年也下降&#xff0c;这部分变化可能与疫情相关。需要对该部分进行必要的解释说明。 问题 1: 基于附件 1 中的数据及您的团队收集的额…

Git简单介绍

一、 Git介绍与安装 1.1 Git简介 Git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理。 1.2集中式(SVN&#xff09; VS 分布式(git) 集中式版本控制系统&#xff0c;版本库是集中存放在中央服务器的&#xff0c;工作时要先从中央…

CSS之3D转换

三维坐标系 三维坐标系其实就是指立体空间&#xff0c;立体空间是由3个轴共同组成的。 x轴:水平向右注意:x右边是正值&#xff0c;左边是负值 y轴:垂直向下注意:y下面是正值&#xff0c;上面是负值 z轴:垂直屏幕注意:往外面是正值&#xff0c;往里面是负值 3D移动 translat…

kafka生产者和消费者命令的使用

kafka-console-producer.sh 生产数据 # 发送信息 指定topic即可 kafka-console-producer.sh \ --bootstrap-server bigdata01:9092 \ --topic topicA # 主题# 进程 29124 ConsoleProducer kafka-console-consumer.sh 消费数据 # 消费数据 kafka-console-consumer.sh \ --boo…

基于Springboot的心灵治愈交流平台系统的设计与实现

基于Springboot的心灵治愈交流平台系统 介绍 基于Springboot的心灵治愈交流平台系统&#xff0c;后端框架使用Springboot和mybatis&#xff0c;前端框架使用Vuehrml&#xff0c;数据库使用mysql&#xff0c;使用B/S架构实现前台用户系统和后台管理员系统&#xff0c;和不同级别…

【人工智能】Python常用库-Scikit-learn常用方法教程

Scikit-learn 是一个功能强大的机器学习库&#xff0c;支持数据预处理、分类、回归、聚类、降维等功能&#xff0c;广泛用于模型开发与评估。以下是 Scikit-learn 的常用方法及详细说明。 1. 安装与导入 安装 Scikit-learn&#xff1a; pip install scikit-learn导入基本模块…

Tcon技术和Tconless技术介绍

文章目录 TCON技术&#xff08;传统时序控制器&#xff09;定义&#xff1a;主要功能&#xff1a;优点&#xff1a;缺点&#xff1a; TCONless技术&#xff08;无独立时序控制器&#xff09;定义&#xff1a;工作原理&#xff1a;优点&#xff1a;缺点&#xff1a; TCON与TCONl…

计算机基础(下)

内存管理 内存管理主要做了什么&#xff1f; 操作系统的内存管理非常重要&#xff0c;主要负责下面这些事情&#xff1a; 内存的分配与回收&#xff1a;对进程所需的内存进行分配和释放&#xff0c;malloc 函数&#xff1a;申请内存&#xff0c;free 函数&#xff1a;释放内存…