【kafka】学习笔记(一)

news2024/11/18 9:34:33

学习笔记

  • 一、概述
    • 1.1、MQ
    • 1.2、kafka
    • 1.3、消息队列的两种模式
      • 1.3.1、点对点
      • 1.3.2、订阅与发布
    • 1.4、Kafka基础架构
  • 二、安装
    • 2.1、 集群规划
    • 2.2、 下载安装
    • 2.3、 集群启动脚本
  • 三、Kafka命令行操作
    • 3.1、主题命令行操作
    • 3.2、生产者命令行操作
    • 3.3、消费者命令行操作
  • 四、 Kafka 生产者
    • 4.1、生产者消息发送流程
      • 4.1.1 发送原理
    • 4.2、 发送实现
      • 4.2.1、不带回调异步发送函数
      • 4.2.2、带回调函数的异步发送
      • 4.2.3、 同步发送
    • 4.3、 生产者分区
      • 4.3.1、分区的好处
      • 4.3.2、分区的策略
      • 4.3.3、自定义分区
    • 4.4、生产者提高吞吐量
    • 4.5、生产者数据可靠性
    • 4.6、数据去重
      • 4.6.1、幂等性
      • 4.6.2、生产者事务

一、概述

1.1、MQ

MQ(message queue),从字面意思上看,本质是个队列,FIFO先入先出,只不过队列中存放的内容是message而已,还是一种跨进程的通信机制,用于上下游传递消息。在互联网架构中,MQ是一种非常常见的上下游“逻辑解耦+物理解耦”的消息通信服务。使用了MQ之后,消息发送上游只需要依赖MQ,不用依赖其他服务。

1.2、kafka

在kafka3.x开始可以不使用Zookeeper 自己可以独立使用

Kafka传统定义:Kafka是一个分布式的基于发布/订阅模式的消息队列(MessageQueue),主要应用于大数据实时处理领域。

发布/订阅:消息的发布者不会将消息直接发送给特定的订阅者,而是将发布的消息分为不同的类别,订阅者只接收感兴趣的消息

Kafka最新定义 : Kafka是一个开源的分布式事件流平台(Event Streaming Platform),被数千家公司用于高性能数据管道、流分析、数据集成和关键任务应用。

异步通信:允许用户把一个消息放入队列,但并不立即处理它,然后在需要的时候再去处理它们

1.3、消息队列的两种模式

1.3.1、点对点

在这里插入图片描述

1.3.2、订阅与发布

在这里插入图片描述

1.4、Kafka基础架构

在这里插入图片描述

二、安装

2.1、 集群规划

kafka01kafka02kafka03
zkzkzk
kafkakafkakafka
192.168.3.34192.168.3.35192.168.3.36

2.2、 下载安装

官方下载地址

下载完上传到服务器(我自己在usr下创建一个叫soft的文件夹上传到这里)

解压

cd /usr/soft
tar -zxvf kafka_2.12-3.0.0.tgz

改解压后文件的名

mv kafka_2.12-3.0.0/ kafka

进入到/opt/module/kafka 目录,修改配置文件server.properties

  1. broker.id
  2. log.dirs
  3. zookeeper.connect
#broker 的全局唯一编号,不能重复,只能是数字。
broker.id=0
#处理网络请求的线程数量
num.network.threads=3
#用来处理磁盘 IO 的线程数量
num.io.threads=8
#发送套接字的缓冲区大小
socket.send.buffer.bytes=102400
#接收套接字的缓冲区大小
socket.receive.buffer.bytes=102400
#请求套接字的缓冲区大小
socket.request.max.bytes=104857600
#kafka 运行日志(数据)存放的路径,路径不需要提前创建,kafka 自动帮你创建,可以配置多个磁盘路径,路径与路径之间可以用","分隔
log.dirs=/usr/soft/kafka/datas
#topic 在当前 broker 上的分区个数
num.partitions=1
#用来恢复和清理 data 下数据的线程数量
num.recovery.threads.per.data.dir=1
# 每个 topic 创建时的副本数,默认时 1 个副本
offsets.topic.replication.factor=1
#segment 文件保留的最长时间,超时将被删除
log.retention.hours=168
#每个 segment 文件的大小,默认最大 1G
log.segment.bytes=107374182
# 检查过期数据的时间,默认 5 分钟检查一次是否数据过期
log.retention.check.interval.ms=300000
#配置连接 Zookeeper 集群地址(在 zk 根目录下创建/kafka,方便管理)
zookeeper.connect=192.168.3.34:2181,192.168.3.35:2181,192.168.3.36:2181/kafka

然后kafka02、kafka02执行上面相同步骤 要改broker.id

配置环境变量/etc/profile

#KAFKA_HOME
export KAFKA_HOME=/usr/soft/kafka
export PATH=$PATH:$KAFKA_HOME/bin
#改完执行
source /etc/profile

启动kafaka前要启动zookeeper
zookeeeper安装教程

zkServer.sh start
zkServer.sh status
#在kafka根目录启动
bin/kafka-server-start.sh -daemon  config/server.properties

输入jps查看启动状态

jps

如果有kafka则启动成功
在这里插入图片描述

2.3、 集群启动脚本

#! /bin/bash
case $1 in
"start"){
 for i in master slave1 slave2
 do
 echo " --------启动 $i Kafka-------"
 ssh $i "/usr/soft/kafka/bin/kafka-server-start.sh -daemon /usr/soft/kafka/config/server.properties"
 done
};;
"stop"){
 for i in master slave1 slave2
 do
 echo " --------停止 $i Kafka-------"
 ssh $i "/usr/soft/kafka/bin/kafka-server-stop.sh "
 done
};;
esac

三、Kafka命令行操作

3.1、主题命令行操作

查看当前服务器中的所有 topic

bin/kafka-topics.sh --bootstrap-server 192.168.3.34:9092 --list

创建 topic

#选项说明:
#--topic 定义 topic 名
#--replication-factor 定义副本数
#--partitions 定义分区数
bin/kafka-topics.sh --bootstrap-server 192.168.3.34:9092 --create --partitions 1 --replication-factor 3 --topic first

查看主题的详情

bin/kafka-topics.sh --bootstrap-server 192.168.3.34:9092 --describe --topic first

修改分区数(分区数只能增加,不能减少)

bin/kafka-topics.sh --bootstrap-server 192.168.3.34:9092 --alter --topic first --partitions 3

删除 topic

bin/kafka-topics.sh --bootstrap-server 192.168.3.34:9092 --delete --topic first

3.2、生产者命令行操作

发送消息

bin/kafka-console-producer.sh --bootstrap-server 192.168.3.34:9092 --topic first
>hello world

3.3、消费者命令行操作

消费消息

bin/kafka-console-consumer.sh --bootstrap-server 192.168.3.34:9092 --topic first

把主题中所有的数据都读取出来(包括历史数据)

bin/kafka-console-consumer.sh --bootstrap-server 192.168.3.34:9092 --from-beginning --topic first

四、 Kafka 生产者

4.1、生产者消息发送流程

4.1.1 发送原理

在消息发送的过程中,涉及到了两个线程——main 线程和 Sender 线程。在 main 线程
中创建了一个双端队列 RecordAccumulator。main 线程将消息发送给 RecordAccumulator,
Sender 线程不断从 RecordAccumulator 中拉取消息发送到 Kafka Broker。
在这里插入图片描述

4.2、 发送实现

pom引入

 <dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
    <version>3.0.0</version>
</dependency>

4.2.1、不带回调异步发送函数

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;
import java.util.Properties;

public class CustomProducer {
    public static void main(String[] args) throws InterruptedException {
        // 1. 创建 kafka 生产者的配置对象
        Properties properties = new Properties();
        // 2. 给 kafka 配置对象添加配置信息:bootstrap.servers
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "master:9092,slave1:9092,slave1:9092");
        // key,value 序列化(必须):key.serializer,value.serializer
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        // 3. 创建 kafka 生产者对象
        KafkaProducer<String, String> kafkaProducer = new KafkaProducer<String, String>(properties);
        // 4. 调用 send 方法,发送消息
        for (int i = 0; i < 5; i++) {
            kafkaProducer.send(new ProducerRecord<>("first","hello " + i));
        }
        // 5. 关闭资源
        kafkaProducer.close();
    }
}

在这里插入图片描述

4.2.2、带回调函数的异步发送

回调函数会在 producer 收到 ack 时调用,为异步调用,该方法有两个参数,分别是元数据信息(RecordMetadata)和异常信息(Exception),如果 Exception 为 null,说明消息发送成功,如果 Exception 不为 null,说明消息发送失败

在这里插入图片描述

消息发送失败会自动重试,不需要我们在回调函数中手动重试

import org.apache.kafka.clients.producer.*;
import org.apache.kafka.common.serialization.StringSerializer;

import java.util.Properties;
public class CustomProducerCallback {
    public static void main(String[] args) throws InterruptedException {
        // 1. 创建 kafka 生产者的配置对象
        Properties properties = new Properties();
        // 2. 给 kafka 配置对象添加配置信息
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"master:9092,slave1:9092,slave1:9092");
        // key,value 序列化(必须):key.serializer,value.serializer
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        // 3. 创建 kafka 生产者对象
        KafkaProducer<String, String> kafkaProducer = new KafkaProducer<String, String>(properties);
        // 4. 调用 send 方法,发送消息
        for (int i = 0; i < 5; i++) {
            // 添加回调
            kafkaProducer.send(new ProducerRecord<>("first", "hello " + i), new Callback() {
                // 该方法在 Producer 收到 ack 时调用,为异步调用
                // 消息发送失败会自动重试,不需要我们在回调函数中手动重试
                @Override
                public void onCompletion(RecordMetadata metadata, Exception exception) {
                    if (exception == null) {
                        // 没有异常,输出信息到控制台
                        System.out.println(" 主题: " + metadata.topic() + "->" + "分区:" + metadata.partition());
                    } else {
                        // 出现异常打印
                        exception.printStackTrace();
                    }
                }
            });
            // 延迟一会会看到数据发往不同分区
            Thread.sleep(2);
        }
        // 5. 关闭资源
        kafkaProducer.close();
    }
}

4.2.3、 同步发送

在这里插入图片描述

4.3、 生产者分区

4.3.1、分区的好处

  1. 便于合理使用存储资源,每个Partition在一个Broker上存储,可以把海量的数据按照分区切割成一块一块数据存储在多台Broker上。合理控制分区的任务,可以实现负载均衡的效果。
  2. 提高并行度,生产者可以以分区为单位发送数据;消费者可以以分区为单位进行消费数据。
    在这里插入图片描述

4.3.2、分区的策略

  1. 指明partition的情况下,直接将指明的值作为partition值;例如partition=0,所有数据写入分区0
  2. 没有指明partition值但有key的情况下,将key的hash值与topic的partition数进行取余得到partition值;例如:key1的hash值=5, key2的hash值=6 ,topic的partition数=2,那么key1 对应的value1写入1号分区,key2对应的value2写入0号分区。
  3. 既没有partition值又没有key值的情况下,Kafka采用Sticky Partition(黏性分区器),会随机选择一个分区,并尽可能一直使用该分区,待该分区的batch已满或者已完成,Kafka再随机一个分区进行使用(和上一次的分区不同)。例如:第一次随机选择0号分区,等0号分区当前批次满了(默认16k)或者linger.ms设置的时间到, Kafka再随机一个分区进行使用(如果还是0会继续随机)。

4.3.3、自定义分区

自定义分区文件

import org.apache.kafka.clients.producer.Partitioner;
import org.apache.kafka.common.Cluster;
import java.util.Map;
/**
 * 1. 实现接口 Partitioner
 * 2. 实现 3 个方法:partition,close,configure
 * 3. 编写 partition 方法,返回分区号
 */
public class MyPartitioner implements Partitioner {
    /**
     * 返回信息对应的分区
     * @param topic 主题
     * @param key 消息的 key
     * @param keyBytes 消息的 key 序列化后的字节数组
     * @param value 消息的 value
     * @param valueBytes 消息的 value 序列化后的字节数组
     * @param cluster 集群元数据可以查看分区信息
     * @return
     */
    @Override
    public int partition(String topic, Object key, byte[] keyBytes,
                         Object value, byte[] valueBytes, Cluster cluster) {
        // 获取消息
        String msgValue = value.toString();
        // 创建 partition
        int partition;
        // 判断消息是否包含 atguigu
        if (msgValue.contains("nacl")){
            partition = 0;
        }else {
            partition = 1;
        }
        // 返回分区号
        return partition;
    }
    // 关闭资源
    @Override
    public void close() {

    }
   // 配置方法
    @Override
    public void configure(Map<String, ?> configs) {

    }
}

使用分区:

// 添加自定义分区器      
properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG,"MyPartitioner 的全类名");   

4.4、生产者提高吞吐量

  • batch.size:批次大小,默认16k
  • linger.ms:等待时间,默认0ms
  • compression.type:压缩snappy ,默认没有
  • RecordAccumulator:缓冲区大小,默认32m
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import java.util.Properties;
public class CustomProducerParameters {
    public static void main(String[] args) throws
            InterruptedException {
        // 1. 创建 kafka 生产者的配置对象
        Properties properties = new Properties();
        // 2. 给 kafka 配置对象添加配置信息:bootstrap.servers
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "master:9092,slave1:9092,slave1:9092");
        // key,value 序列化(必须):key.serializer,value.serializer
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
        // batch.size:批次大小,默认 16K
        properties.put(ProducerConfig.BATCH_SIZE_CONFIG, 16384);
        // linger.ms:等待时间,默认 0
        properties.put(ProducerConfig.LINGER_MS_CONFIG, 1);
        // RecordAccumulator:缓冲区大小,默认 32M:buffer.memory
        properties.put(ProducerConfig.BUFFER_MEMORY_CONFIG,33554432);
        // compression.type:压缩,默认 none,可配置值 gzip、snappy、lz4 和 zstd
        properties.put(ProducerConfig.COMPRESSION_TYPE_CONFIG,"snappy");
        // 3. 创建 kafka 生产者对象
        KafkaProducer<String, String> kafkaProducer = new KafkaProducer<String, String>(properties);
        // 4. 调用 send 方法,发送消息
        for (int i = 0; i < 5; i++) {
            kafkaProducer.send(new
                    ProducerRecord<>("first","world " + i));
        }
        // 5. 关闭资源
        kafkaProducer.close();
    }
}

4.5、生产者数据可靠性

ack 应答:
0:生产者发送过来的数据,不需要等数据落盘应答。可靠性差,效率高;
1:生产者发送过来的数据,Leader收到数据后应答。可靠性中等,效率中等;
-1(all):生产者发送过来的数据,Leader和ISR队列里面的所有节点收齐数据后应答。可靠性高,效率低;

Leader维护了一个动态的in-sync replica set(ISR),意为和Leader保持同步的Follower+Leader集合(leader:0,isr:0,1,2)。如果Follower长时间未向Leader发送通信请求或同步数据,则该Follower将被踢出ISR。该时间阈值由replica.lag.time.max.ms参数设定,默认30s。例如2超时,(leader:0, isr:0,1)。这样就不用等长期联系不上或者已经故障的节点。

数据完全可靠条件 = ACK级别设置为-1 + 分区副本大于等于2 + ISR里应答的最小副本数量大于等于2

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;

import java.util.Properties;
public class CustomProducerAck {
    public static void main(String[] args) throws InterruptedException {
        // 1. 创建 kafka 生产者的配置对象
        Properties properties = new Properties();
        // 2. 给 kafka 配置对象添加配置信息:bootstrap.servers
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "master:9092,slave1:9092,slave1:9092");
        // key,value 序列化(必须):key.serializer,value.serializer
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
        // 设置 acks
        properties.put(ProducerConfig.ACKS_CONFIG, "all");
        // 重试次数 retries,默认是 int 最大值,2147483647
        properties.put(ProducerConfig.RETRIES_CONFIG, 3);
        // 3. 创建 kafka 生产者对象
        KafkaProducer<String, String> kafkaProducer = new KafkaProducer<String, String>(properties);
        // 4. 调用 send 方法,发送消息
        for (int i = 0; i < 5; i++) {
            kafkaProducer.send(new ProducerRecord<>("first","nacl " + i));
        }
        // 5. 关闭资源
        kafkaProducer.close();
    }
}

4.6、数据去重

重复数据的判断标准:具有<PID, Partition, SeqNumber>相同主键的消息提交时,Broker只会持久化一条。
PID是Kafka每次重启都会分配一个新的;
Partition 表示分区号;
Sequence Number是单调自增的。

4.6.1、幂等性

幂等性就是指Producer不论向Broker发送多少次重复数据,Broker端都只会持久化一条,保证了不重复。
所以幂等性只能保证的是在单分区单会话内不重复

开启参数 enable.idempotence 默认为 truefalse 关闭。

4.6.2、生产者事务

在这里插入图片描述

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;

import java.util.Properties;
public class CustomProducerTransactions {
    public static void main(String[] args) throws
            InterruptedException {
        // 1. 创建 kafka 生产者的配置对象
        Properties properties = new Properties();
        // 2. 给 kafka 配置对象添加配置信息
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"master:9092,slave1:9092,slave1:9092");
        // key,value 序列化
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        // 设置事务 id(必须),事务 id 任意起名
        properties.put(ProducerConfig.TRANSACTIONAL_ID_CONFIG, "transaction_id_0");
        // 3. 创建 kafka 生产者对象
        KafkaProducer<String, String> kafkaProducer = new KafkaProducer<String, String>(properties);
        // 初始化事务
        kafkaProducer.initTransactions();
        // 开启事务
        kafkaProducer.beginTransaction();
        try {
            // 4. 调用 send 方法,发送消息
            for (int i = 0; i < 5; i++) {
                // 发送消息
                kafkaProducer.send(new ProducerRecord<>("first", "hello " + i));
            }
            //int i = 1 / 0;
            // 提交事务
            kafkaProducer.commitTransaction();
        } catch (Exception e) {
            // 终止事务
            kafkaProducer.abortTransaction();
        } finally {
            // 5. 关闭资源
            kafkaProducer.close();
        }
    }
}

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

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

相关文章

常用的Linux命令介绍

ls&#xff1a; 如何区分一个文件类型是 文件夹 还是 普通文件&#xff1a; “-” 类型 表示是 普通文件 “d” 类型 表示是 文件夹 cd&#xff1a; cd -返回进入此目录前所在的目录 cd ~如果是root用户&#xff0c;相当于 cd /root&#xff1b;如果是普通用户&#xff0c;相…

7、操作系统之间的文件传输

Windows 与 Linux 在Windows与Linux中传输文件的常用方式有两种&#xff0c;一种是使用使用XFTP工具&#xff0c;另一种是使用rz sz 命令的方式进行 lrzsz 安装 yum install lrzsz -y 1&#xff09;rz 将文件从window上传到Linux 2&#xff09;sz 将文件从linux传输到window …

常用排序算法哪个效率更高之从理论到实践

前面整理了一篇关于排序算法的基础类库&#xff1a;基本排序算法类SortHelper 这里我们来看看这几个算法哪个效率更高一点呢&#xff1f; 1、先从理论来看看这几个算法 1、冒泡排序法 基本思想&#xff1a;两两比较待排序数据元素的大小&#xff0c;发现两个数据元素的次序…

RSA和AES的使用

文章目录为什么要对数据传输加密对称加密和非对称加密密钥的几种格式非对称加密算法----RSA算法产生公私密钥对对称加解密算法AES为什么要结合使用这两种算法利用RSA来加密传输AES的密钥&#xff0c;用AES来加密数据&#xff0c;思路如下&#xff1a;特点分析&#xff1a;参考链…

【探索Spring底层】14.谈谈参数解析器

文章目录1. 参数解析器概述2. 常见参数的解析1. 参数解析器概述 参数解析器是Spring-Web包提供的组件&#xff0c;并且SpringMVC中提供了很多参数解析器。 常见的参数解析器如下 org.springframework.web.method.annotation.RequestParamMethodArgumentResolverabbc908org.s…

部署并启动项目在linux(CentOS7)上,一名合格的程序猿不能不会(ಥ_ಥ)

各位小伙伴大家好呀哈哈哈~ 遇到问题不要慌─≡Σ(((つ•̀ω•́)つ让我先发个朋友圈~( • ̀ω•́ )✧ 我们知道项目的正常运行是需要先部署在服务器上&#xff0c;然后才能正常使用&#xff0c;我们一般都是在idea下写好然后直接部署在tomcat上或者其他服务器&#xff0c;但…

多维表需求管理表自动生成TAPD需求

【实现效果&#xff1a;】业务同学使用多维表管理客户需求&#xff0c;和产品团队经过评审之后&#xff0c;一键把多维表里对应的需求生成TAPD需求/缺陷单 【准备工作】 准备一个多维表&#xff0c;比如维格表、金山轻维表等 可以参考这两个模版&#xff1a; 金山轻维表&am…

【深入浅出Spring原理及实战】「开发实战系列」Aspectj和LoadTimeWeaving的动态代理技术实现指南

前提介绍 当我们聊到Spring框架的项目实际开发中&#xff0c;用的强大的功能之一就是&#xff08;面向切面编程&#xff09;的这门AOP技术。如果使用得当&#xff0c;它的最大的作用就是侵入性比较少并且简化我们的工作任务&#xff08;节省大量的重复性编码&#xff09;&…

【QT】PySide6 数据可视化折线图

一、项目介绍 本项目将通过PySide6构建一个可以显示数据折线图的可视化程序&#xff0c;其中&#xff0c;数据来源时美国地质调查局(US Geological Survey)上公开的一小时地震震级数据。 可以通过链接进行下载。 二、实现步骤 本项目的实现步骤可以概括为&#xff1a; 读取…

艾美捷过氧化氢酶检测试剂盒的功能和应用

过氧化氢酶&#xff08;EC 1.11.1.6&#xff1b;2H2O2氧化还原酶&#xff09;是一种普遍存在于大多数需氧细胞中的抗氧化酶。过氧化氢酶&#xff08;CAT&#xff09;参与过氧化氢&#xff08;H2O2&#xff09;的解毒&#xff0c;过氧化氢是一种活性氧&#xff08;ROS&#xff0…

领域首创!合合信息与上海大学联合开启贵州原生态古彝文典籍数字化项目

古彝文传承至今已有数千年历史&#xff0c;是世界上最古老的文字之一。2022年12月21日&#xff0c;合合信息与上海大学社会学院正式签署校企合作协议&#xff0c;双方将合力完成以国家珍贵古籍《西南彝志》为中心的贵州古彝文图像识别及数字化校对项目&#xff08;简称“古彝文…

搜索与图论---最短路

最短路:建图! 源点—起点汇点—终点约定n为点数,m为边数1单源最短路:求一个点到其他所有点的最短路 1.1所有边权都是正数 (1)朴素的Dijkstra算法(On^2) 例题:Dijkstra求最短路 I 代码: #include<iostream> #include<cstring> #

代码随想录算法训练营第42天 | 01背包问题 416. 分割等和子集

01背包问题 由于leetcode上没原题&#xff0c;故参考卡哥意见自己编题记录一下。 一、题干 背包最大重量为4。物品为&#xff1a; 物品名称重量价值011513202430––– 问背包能背的物品最大价值是多少&#xff1f; 二、解法 二维dp&#xff1a; 递推公式&#xff1a;dp[i…

数组方法中会更改原数组,不会更改原数组(详细)

1.不会改变原来数组的有&#xff1a; concat() 连接两个或更多的数组&#xff0c;并返回结果。 如果arr.concat&#xff08;&#xff09;里面不放数组参数&#xff0c;则会浅拷贝arr 如果参数不是数组&#xff0c;它不会递归到嵌套数组参数中 数据类型如字符串&#xff0c;数…

elasticsearch小白入门

一般再项目中都会用到 搜索&#xff0c;如果直接查询数据库&#xff0c;性能会存在瓶颈。 这时&#xff0c;用ES就很好的解决这个问题。 ES组件很多&#xff1a;包括 elasticsearch kibana beats logstash 安装 elasticsearch 下载&#xff1a; Elasticsearch 7.10.2 | El…

SpringBoot项目搭建+登录功能实现(小结)

项目目录 登录功能实现思路 目录 1.pom.xml添加依赖 2.配置application.yml文件 3.sql映射文件配置---UserMapper.xml 4.导入页面资源 5.Springboot启动类的配置 6.编写全局配置类 config->AppConfig 7.创建实体类--数据表对应 8.修改login.html页面 9.编写UserCo…

基于SpringBoot的SSMP整合案例

基于SpringBoot的SSMP整合案例 简介&#xff1a;SSMP(SpringSpringMVCMyBatis)&#xff0c;通过SpringBoot整合SSMP来完成增删改查案例。 功能开发模块 实体类开发————使用Lombok快速制作实体类Dao开发————整合MyBatisPlus&#xff0c;制作数据层测试Service开发——…

如意如意猿如意

如意如意猿如意什么是猿如意猿如意效率工具JSON编辑器jsontojava开发工具ChatGPT推荐指数评分及改进意见UI界面效率工具和开发工具ChatGPT一行代码总结经常听到一句话&#xff1a;如意如意随我心意&#xff0c;作为程序猿&#xff0c;我也想要一个如意&#xff0c;心中默念咒语…

LeetCode-91-解码方法

1、动态规划法 我们可以使用动态规划法来解决本问题。我们利用数组dp[i]dp[i]dp[i]来记录字符串前iii位能够组成的解码方法总数。在设计状态转移方程时&#xff0c;我们需要注意这样子的特殊情况&#xff1a;1、当s[i]s[i]s[i]不为0时&#xff0c;单独一个s[i]s[i]s[i]肯定能够…

PID算法总结-从公式原理到参数整定解析

目录 一、控制系统 1.1控制系统的分类 1.2 性能指标 二、PID算法的起源及特点 三、PID应用 四、PID公式原理 五、PID源码 六、PID整定方法 6.1 经验法 6.2 衰减曲线法 6.3 响应曲线法 参考文献&#xff1a; 一、控制系统 1.1控制系统的分类 分为开环控制、闭环控制和复…