【大数据学习 | kafka】producer之拦截器,序列化器与分区器

1. 自定义拦截器

interceptor是拦截器,可以拦截到发送到kafka中的数据进行二次处理,它是producer组成部分的第一个组件。

public static class MyInterceptor implements ProducerInterceptor<String,String>{@Overridepublic ProducerRecord<String, String> onSend(ProducerRecord<String, String> record) {return null;}@Overridepublic void onAcknowledgement(RecordMetadata metadata, Exception exception) {}@Overridepublic void close() {}@Overridepublic void configure(Map<String, ?> configs) {}}

实现拦截器需要实现ProducerInterceptor这个接口,其中的泛型要和producer端发送的数据的类型一致。

onSend方法是最主要的方法用户拦截数据并且处理完毕发送
onAcknowledgement 获取确认应答的方法,这个方法和producer端的差不多,只能知道结果通知
close是执行完毕拦截器最后执行的方法
configure方法是用于获取配置文件信息的方法

我们拦截器的实现基于场景是获取到producer端的数据然后给数据加上时间戳。

整体代码如下:

package com.hainiu.kafka.producer;/*** ClassName : producer_intercepter* Package : com.hainiu.kafka.producer* Description** @Author HeXua* @Create 2024/10/31 22:56* Version 1.0*/import org.apache.kafka.clients.producer.*;
import org.apache.kafka.common.serialization.StringSerializer;import java.util.Date;
import java.util.Map;
import java.util.Properties;public class producer_intercepter {public static class MyInterceptor implements ProducerInterceptor<String,String>{@Overridepublic ProducerRecord<String, String> onSend(ProducerRecord<String, String> record) {String value = record.value();Long time = new Date().getTime();String topic = record.topic();//获取原始数据并且构建新的数据,增加时间戳信息return new ProducerRecord<String,String>(topic,time+"-->"+value);}@Overridepublic void onAcknowledgement(RecordMetadata metadata, Exception exception) {//获取确认应答和producer端的代码逻辑相同String topic = metadata.topic();int partition = metadata.partition();long offset = metadata.offset();if(exception == null ){System.out.println("success"+" "+topic+" "+partition+" "+offset);}else{System.out.println("fail"+" "+topic+" "+partition+" "+offset);}}@Overridepublic void close() {//不需要任何操作//no op}@Overridepublic void configure(Map<String, ?> configs) {//不需要任何操作//no op}}public static void main(String[] args) {Properties pro = new Properties();pro.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"hadoop106:9092");pro.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());pro.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());pro.put(ProducerConfig.ACKS_CONFIG, "all");pro.put(ProducerConfig.RETRIES_CONFIG,3 );pro.put(ProducerConfig.BATCH_SIZE_CONFIG, 16*1024);pro.put(ProducerConfig.LINGER_MS_CONFIG, 0);pro.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG,MyInterceptor.class.getName());//设定拦截器KafkaProducer<String, String> producer = new KafkaProducer<String, String>(pro);ProducerRecord<String, String> record = new ProducerRecord<>("topic_a", "this is hainiu");for(int i=0;i<5;i++){producer.send(record, new Callback() {@Overridepublic void onCompletion(RecordMetadata metadata, Exception exception) {String topic = metadata.topic();int partition = metadata.partition();long offset = metadata.offset();if(exception == null ){System.out.println("success"+" "+topic+" "+partition+" "+offset);}else{System.out.println("fail"+" "+topic+" "+partition+" "+offset);}}});}producer.close();}
}

ack返回的元数据信息。

success topic_a 0 17
success topic_a 0 17
success topic_a 0 18
success topic_a 0 18
success topic_a 0 19
success topic_a 0 19
success topic_a 0 20
success topic_a 0 20
success topic_a 0 21
success topic_a 0 21

查看consumer端消费的数据。

f287b3bf12054f0bbeea073f9b3dcd66.png

在客户端消费者中可以打印出来信息带有时间戳。

拦截器一般很少人为定义,比如一般producer在生产环境中都是有flume替代,一般flume会设定自己的时间戳拦截器,指定数据采集时间,相比producer更加方便实用。

2. 自定义序列化器

kafka中的数据存储是二进制的byte数组形式,所以我们在存储数据的时候要使用序列化器进行数据的转换,序列化器的结构要和存储数据的kv的类型一致。

比如我们要实现系统的String类型序列化器。

2.1 实现String类型的序列化器

package com.hainiu.kafka.producer;/*** ClassName : producer_String_Serializer* Package : com.hainiu.kafka.producer* Description** @Author HeXua* @Create 2024/10/31 23:12* Version 1.0*/
import org.apache.kafka.clients.producer.*;
import org.apache.kafka.common.serialization.Serializer;
import org.apache.kafka.common.serialization.StringSerializer;import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Properties;public class producer_String_Serializer {public static void main(String[] args) {Properties pro = new Properties();//bootstrap-server key value batch-size linger.ms ack retries interceptorpro.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"hadoop106:9092");// 自定义生产记录的key和value的序列化器pro.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, MyStringSerializer.class.getName());pro.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, MyStringSerializer.class.getName());pro.put(ProducerConfig.BATCH_SIZE_CONFIG,16*1024);pro.put(ProducerConfig.LINGER_MS_CONFIG,0);pro.put(ProducerConfig.ACKS_CONFIG,"all");pro.put(ProducerConfig.RETRIES_CONFIG,3);KafkaProducer<String, String> producer = new KafkaProducer<String, String>(pro);for (int i = 0; i < 100; i++) {ProducerRecord<String, String> record = new ProducerRecord<>("topic_a", "hainiu","message_" + i);producer.send(record);}producer.close();}public static class MyStringSerializer implements Serializer<String>{@Overridepublic byte[] serialize(String topic, String data) {return data.getBytes(StandardCharsets.UTF_8);}}
}

消费者消费数据:

message_0
message_1
message_2
message_3
message_4
message_5
message_6
message_7
message_8
message_9
message_10
message_11
message_12
..........

2.2 序列化对象整体

package com.hainiu.kafka.producer;/*** ClassName : producer_Student_Serializer* Package : com.hainiu.kafka.producer* Description** @Author HeXua* @Create 2024/10/31 23:20* Version 1.0*/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.Serializer;
import org.apache.kafka.common.serialization.StringSerializer;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.Properties;/*** producerRecord==> key:string,value:student*/
public class producer_Student_Serializer {public static class Student implements Serializable{private int id;private String name;private int age;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Student() {}public Student(int id, String name, int age) {this.id = id;this.name = name;this.age = age;}}public static class MyStudentSerializer implements Serializer<Student>{//        ByteArrayOutputStream
//        ObjectOutputStream@Overridepublic byte[] serialize(String topic, Student data) {ByteArrayOutputStream byteOS = null;ObjectOutputStream objectOS = null;try {byteOS =new ByteArrayOutputStream();objectOS = new ObjectOutputStream(byteOS);objectOS.writeObject(data);} catch (IOException e) {throw new RuntimeException(e);}finally {try {byteOS.close();objectOS.close();} catch (IOException e) {throw new RuntimeException(e);}}return byteOS.toByteArray();}}public static void main(String[] args) {Properties pro = new Properties();//bootstrap-server key value batch-size linger.ms ack retries interceptorpro.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"hadoop106:9092");pro.put(ProducerConfig.BATCH_SIZE_CONFIG,16*1024);pro.put(ProducerConfig.LINGER_MS_CONFIG,0);pro.put(ProducerConfig.ACKS_CONFIG,"all");pro.put(ProducerConfig.RETRIES_CONFIG,3);pro.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());pro.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,MyStudentSerializer.class.getName());KafkaProducer<String, Student> producer = new KafkaProducer<>(pro);Student s1 = new Student(1, "zhangsan", 20);Student s2 = new Student(2, "lisi", 30);ProducerRecord<String, Student> r1 = new ProducerRecord<>("topic_a", "hainiu", s1);ProducerRecord<String, Student> r2 = new ProducerRecord<>("topic_a", "hainiu", s2);producer.send(r1);producer.send(r2);producer.close();}

消费的数据:

[hexuan@hadoop107 kafka]$ kafka-console-consumer.sh --bootstrap-server hadoop106:9092 --topic topic_a
¬첲=com.hainiu.kafka.producer.producer_Student_Serializer$Student8Ӯ¥ClOIageIidLnametLjava/lang/String;xpzhangsan
¬첲=com.hainiu.kafka.producer.producer_Student_Serializer$Student8Ӯ¥ClOIageIidLnametLjava/lang/String;xptlisi
XshellXshell

2.3 序列化对象字段信息

比如我们想要发送一个Student对象,其中包含id name age等字段,这个数据需要对应的序列化器

序列化器的实现需要指定类型并且实现。

需要实现serializer接口,并且实现serialize的方法用于将数据对象转换为二进制的数组

整体代码如下:

package com.hainiu.kafka.producer;/*** ClassName : producer_Student_Serializer2* Package : com.hainiu.kafka.producer* Description** @Author HeXua* @Create 2024/10/31 23:30* Version 1.0*/
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.Serializer;
import org.apache.kafka.common.serialization.StringSerializer;import java.nio.charset.Charset;
import java.util.Properties;public class producer_Student_Serializer2 {public static void main(String[] args) {Properties pro = new Properties();pro.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"hadoop106:9092");pro.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());//key因为没有放入任何值,所以序列化器使用原生的就可以pro.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StudentSeria.class.getName());//value的序列化器需要指定相应的student序列化器pro.put(ProducerConfig.BATCH_SIZE_CONFIG, 16*1024);pro.put(ProducerConfig.LINGER_MS_CONFIG, 0);KafkaProducer<String, Student> producer = new KafkaProducer<String, Student>(pro);//producer生产的数据类型也必须是string,student类型的kvStudent student = new Student(1, "zhangsan", 30);ProducerRecord<String, Student> record = new ProducerRecord<>("topic_a", student);producer.send(record);producer.close();}public static class Student{private int id;private String name;private int age;public int getId() {return id;}public Student() {}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Student(int id, String name, int age) {this.id = id;this.name = name;this.age = age;}}public static class StudentSeria implements Serializer<Student> {@Overridepublic byte[] serialize(String topic, Student data) {String line =data.getId()+" "+data.getName()+" "+data.getAge();//获取student对象中的所有数据信息return line.getBytes(Charset.forName("utf-8"));//转换为byte数组返回}}
}

消费者消费数据:

[hexuan@hadoop107 kafka]$ kafka-console-consumer.sh --bootstrap-server hadoop106:9092 --topic topic_a
1 zhangsan 30

3. 分区器

首先在kafka存储数据的时候topic中的数据是分为多个分区进行存储的,topic设定分区的好处是可以进行分布式存储和分布式管理,那么好的分区器可以让数据尽量均匀的分布到不同的机器节点,数据更加均匀,那么kafka中的分区器是如果实现的呢?

2a56135210124f0bab06d60d1dfbbd20.png

根据图我们可以看出数据首先通过分区器进行分类在本地的累加器中进行存储缓存然后在复制到kafka集群中,所以分区器产生作用的位置在本地的缓存之前。

kafka的分区规则是如何实现的呢?

ProducerRecord<String, Student> record = new ProducerRecord<>("topic_a", student);
producer.send(record);

kafka的生产者数据发送是通过上面的方法实现的

首先要构造一个ProducerRecord对象,然后通过producer.send来进行发送数据。

其中ProducerRecord对象的构造器种类分为以下几种。

1. 构造器指定分区,包含key, value。

2. 构造器没有指定分区,但有key,有value。

3. 构造器只有value。

/*** Creates a record to be sent to a specified topic and partition** @param topic The topic the record will be appended to* @param partition The partition to which the record should be sent* @param key The key that will be included in the record* @param value The record contents*/
public ProducerRecord(String topic, Integer partition, K key, V value) {this(topic, partition, null, key, value, null);}/*** Create a record to be sent to Kafka* * @param topic The topic the record will be appended to* @param key The key that will be included in the record* @param value The record contents*/
public ProducerRecord(String topic, K key, V value) {this(topic, null, null, key, value, null);
}/*** Create a record with no key* * @param topic The topic this record should be sent to* @param value The record contents*/
public ProducerRecord(String topic, V value) {this(topic, null, null, null, value, null);
}

我们想要发送一个数据到kafka的时候可以构造以上的ProducerRecord但是构造的方式却不同,大家可以发现携带的参数也有所不同,当携带不同参数的时候数据会以什么样的策略发送出去呢,这个时候需要引入一个默认分区器,就是在用户没有指定任何规则的时候系统自带的分区器规则。

在ProducerConfig源码中看到:

public static final String PARTITIONER_CLASS_CONFIG = "partitioner.class";private static final String PARTITIONER_CLASS_DOC = "A class to use to determine which partition to be send to when produce the records. Available options are:" +"<ul>" +"<li>If not set, the default partitioning logic is used. " +"This strategy will try sticking to a partition until " + BATCH_SIZE_CONFIG + " bytes is produced to the partition. It works with the strategy:" +"<ul>" +"<li>If no partition is specified but a key is present, choose a partition based on a hash of the key</li>" +"<li>If no partition or key is present, choose the sticky partition that changes when " + BATCH_SIZE_CONFIG + " bytes are produced to the partition.</li>" +"</ul>" +"</li>" +"<li><code>org.apache.kafka.clients.producer.RoundRobinPartitioner</code>: This partitioning strategy is that " +"each record in a series of consecutive records will be sent to a different partition(no matter if the 'key' is provided or not), " +"until we run out of partitions and start over again. Note: There's a known issue that will cause uneven distribution when new batch is created. " +"Please check KAFKA-9965 for more detail." +"</li>" +"</ul>" +"<p>Implementing the <code>org.apache.kafka.clients.producer.Partitioner</code> interface allows you to plug in a custom partitioner.";

在producerConfig对象中我们可以看到源码指示,如果没有任何人为分区器规则指定,那么默认使用的DefaultPartitioner的规则.

package org.apache.kafka.clients.producer.internals;import org.apache.kafka.clients.producer.Partitioner;
import org.apache.kafka.common.Cluster;import java.util.Map;/*** NOTE this partitioner is deprecated and shouldn't be used.  To use default partitioning logic* remove partitioner.class configuration setting.  See KIP-794 for more info.** The default partitioning strategy:* <ul>* <li>If a partition is specified in the record, use it* <li>If no partition is specified but a key is present choose a partition based on a hash of the key* <li>If no partition or key is present choose the sticky partition that changes when the batch is full.* * See KIP-480 for details about sticky partitioning.*/
@Deprecated
public class DefaultPartitioner implements Partitioner {private final StickyPartitionCache stickyPartitionCache = new StickyPartitionCache();public void configure(Map<String, ?> configs) {}/*** Compute the partition for the given record.** @param topic The topic name* @param key The key to partition on (or null if no key)* @param keyBytes serialized key to partition on (or null if no key)* @param value The value to partition on or null* @param valueBytes serialized value to partition on or null* @param cluster The current cluster metadata*/public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {return partition(topic, key, keyBytes, value, valueBytes, cluster, cluster.partitionsForTopic(topic).size());}/*** Compute the partition for the given record.** @param topic The topic name* @param numPartitions The number of partitions of the given {@code topic}* @param key The key to partition on (or null if no key)* @param keyBytes serialized key to partition on (or null if no key)* @param value The value to partition on or null* @param valueBytes serialized value to partition on or null* @param cluster The current cluster metadata*/public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster,int numPartitions) {if (keyBytes == null) {return stickyPartitionCache.partition(topic, cluster);}return BuiltInPartitioner.partitionForKey(keyBytes, numPartitions);}public void close() {}/*** If a batch completed for the current sticky partition, change the sticky partition. * Alternately, if no sticky partition has been determined, set one.*/@SuppressWarnings("deprecation")public void onNewBatch(String topic, Cluster cluster, int prevPartition) {stickyPartitionCache.nextPartition(topic, cluster, prevPartition);}
}

而打开DefaultPartitioner以后可以看到他的分区器规则,就是在构建ProducerRecord的时候

new ProducerRecord(topic,partition,k,v);
//指定分区直接发送数据到相应分区中
new ProducerRecord(topic,k,v);
//没有指定分区就按照k的hashcode发送到不同分区
new ProducerRecord(topic,v);
//如果k和partition都没有指定就使用粘性分区

partition方法中,如果key为空就放入到粘性缓冲中,它的意思就是如果满足batch-size或者linger.ms就会触发应用执行,将数据复制到kafka中,并且再次随机到其他分区,所以简单来说粘性分区就是可一个分区放入数据,一旦满了以后才会改变分区,粘性分区规则使用主要是为了让每次复制数据更加快捷方便都赋值到一个分区中。

而如果key不为空那么就按照hashcode值进行取余处理。(哈希分区器)

总的来说就是分为默认分区分为三种情况:

1. 如果指定了分区,就复制到kafka集群指定的分区。

2. 如果没有指定分区,但又有key存在,那么将会对key求哈希值再取余。

即 key.hashCode()%numPartition,将得到一个数字,消息将会被复制到kafka集群的该数字对应的分区。

3. 如果没有指定分区,并且不存在key,只有value。那么我们会采用粘性分区策略。

即产生一个随机值k,并将没有key的记录都放入粘性缓冲,如果满足batch-size或者linger.ms就会触发应用执行,将粘性缓冲的消息复制到kafka集群随机一个分区。然后重复此步骤。

 

 

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

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

相关文章

基于Spring Boot的高校物品捐赠管理系统设计与实现,LW+源码+讲解

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装高校物品捐赠管理系统软件来发挥其高效地信息处理的作用&a…

推荐FileLink数据跨网摆渡系统 — 安全、高效的数据传输解决方案

在数字化转型的浪潮中&#xff0c;企业对于数据传输的需求日益增加&#xff0c;特别是在不同网络环境之间的文件共享和传输。为了满足这一需求&#xff0c;FileLink数据跨网摆渡系统应运而生&#xff0c;为企业提供了一种安全、高效的数据传输解决方案。 安全第一&#xff0c;保…

C++_day2

目录 1. 引用 reference&#xff08;重点&#xff09; 1.1 基础使用 1.2 特性 1.3 引用参数 2. C窄化&#xff08;了解&#xff09; 3. 输入&#xff08;熟悉&#xff09; 4. string 字符串类&#xff08;掌握&#xff09; 4.1 基础使用 4.2 取出元素 4.3 字符串与数字转换 5. …

服务器数据恢复—RAID5阵列硬盘坏道掉线导致存储不可用的数据恢复案例

服务器存储数据恢复环境&#xff1a; 一台EqualLogic存储中有一组由16块SAS硬盘组建的RAID5阵列。上层划分了4个卷&#xff0c;采用VMFS文件系统&#xff0c;存放虚拟机文件。 服务器存储故障&#xff1a; 存储RAID5阵列中磁盘出现故障&#xff0c;有2块硬盘对应的指示灯亮黄灯…

25国考照片处理器使用流程图解❗

1、打开“国家公务员局”网站&#xff0c;进入2025公务员专题&#xff0c;找到考生考务入口 2、点击下载地址 3、这几个下载链接都可以 4、下载压缩包 5、解压后先看“使用说明”&#xff0c;再找到“照片处理工具”双击。 6、双击后会进入这样的界面&#xff0c;点击&…

2024年云手机推荐榜单:高性能云手机推荐

无论是手游玩家、APP测试人员&#xff0c;还是数字营销工作者&#xff0c;云手机都为他们带来了极大的便利。本文将为大家推荐几款在市场上表现优异的云手机&#xff0c;希望这篇推荐指南可以帮助大家找到最适合自己的云手机&#xff01; 1. OgPhone云手机 OgPhone云手机是一款…

JeecgBoot入门

最近在了解低代码平台&#xff0c;其中关注到gitee上开源项目JeecgBoot&#xff0c;JeecgBoot官方也有比较完整的入门教学文档&#xff0c;这里我们将耕者官方教程学习&#xff0c;并将其记录下来。 一、项目简介 JeecgBoot 是一款基于代码生成器的低代码开发平台拥有零代码能力…

Java基础语法①Java特点+环境安装+IDEA使用

目录 1. Java的概念和用途 1.1 Java的概念和发展史 1.2 Java的重要性 1.3 Java的特点 2. Java环境 2.1 JVM 和 JDK 2.2 Java环境安装 2.3 安装IntelliJ IDEA并使用 2.4 IntelliJ IDEA常见快捷键 2.4.1 普通快捷键 2.4.2 调试快捷键 2.4.3 代码生成快捷键 本篇完 写…

windows与windows文件共享

目录 基础设置主机共享文件端设置从机接受文件端设置 基础设置 1、先确保两台电脑直接能够ping通&#xff0c;这是文件共享的前提&#xff0c;如果ping不通就去查找对应的原因&#xff0c;一般都是防火墙的原因。 在ping通的情况下&#xff1a; 2、先找到高级共享设置 3、对专…

Unity3D 开发教程:从入门到精通

Unity3D 开发教程&#xff1a;从入门到精通 Unity3D 是一款强大的跨平台游戏引擎&#xff0c;广泛应用于游戏开发、虚拟现实、增强现实等领域。本文将详细介绍 Unity3D 的基本概念、开发流程以及一些高级技巧&#xff0c;帮助你从零基础到掌握 Unity3D 开发。 目录 Unity3D…

[算法初阶]第二集 滑动窗口(已完结)

大家好啊,好久没有更新了,最近比较忙,所以来更新初阶算法,正好复习一下,感谢大家的观看,如有错误欢迎指出。 下面我们来看题目吧&#xff01; 1.209. 长度最小的子数组 这题大家想必一眼就看出了解法一暴力法 这个解法很简单 代码如下,不做多的解释 class Solution { publi…

恋爱脑学Rust之Box与RC的对比

在遥远的某个小镇&#xff0c;住着一对年轻的恋人&#xff1a;阿丽和小明。他们的爱情故事就像 Rust 中的 Rc 和 Box 智能指针那样&#xff0c;有着各自不同的「所有权」和「共享」的理解。 故事背景 阿丽和小明准备共同养一株非常珍贵的花&#xff08;我们称之为“心之花”&…

Move Dev Meetup@Beijing圆满结束,发掘Move生态新机会

Sui、Aptos 、Rooch 和 zkMove等为代表的 Move 生态在 2024 年展现出强劲的生命力和发展速度。随着技术的持续演进&#xff0c;Move 语言的独特优势吸引了大量优质项目、开发者、投资者和爱好者的参与&#xff0c;共同推动生态建设和创新应用。新一轮技术革新已经开启&#xff…

Python | Leetcode Python题解之第530题二叉搜索树的最小绝对差

题目&#xff1a; 题解&#xff1a; # Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val x # self.left None # self.right Noneclass Solution(object):def isValidBST(self, root):"…

数字经济赋能新质生产力数据集-dta格式(2012-2022年)

数据简介&#xff1a;新质生产力以新发展理念为思想指引&#xff0c;驱动数字经济创新发展动力、推动区域协调发展、转变发展方式、拓宽国际市场、共享数据要素&#xff0c;为数字经济高质量发展提供强大 动力支持。数字经济在发展过程中可能会存在关键性技术创新能力不足、传统…

Oracle视频基础1.4.3练习

15个视频 1.4.3 できない dbca删除数据库 id ls cd cd dbs ls ls -l dbca# delete a database 勾选 # chris 勾选手动删除数据库 ls ls -l ls -l cd /u01/oradata ls cd /u01/admin/ ls cd chris/ ls clear 初始化参数文件&#xff0c;admin&#xff0c;数据文件#新版本了…

.net core 接口,动态接收各类型请求的参数

[HttpPost] public async Task<IActionResult> testpost([FromForm] object info) { //Postman工具测试结果&#xff1a; //FromBody,Postman的body只有rawjson时才进的来 //参数为空时&#xff0c;Body(form-data、x-www-form-urlencoded)解析到的数据也有所…

《JVM第5课》虚拟机栈

无痛快速学习入门JVM&#xff0c;欢迎订阅本免费专栏 Java虚拟机栈&#xff08;Java Virtual Machine Stack&#xff0c;简称JVM栈&#xff0c;又称Java方法栈&#xff09;是 JVM 运行时数据区的一部分&#xff0c;主要用于支持Java方法的执行。每当一个新线程被创建时&#xf…

Axure大屏可视化模板:赋能各行各业的数据展示与管理

如何高效、直观地展示和分析数据&#xff0c;成为企业和机构面临的重要挑战。Axure大屏可视化模板作为一种先进的数据展示工具&#xff0c;凭借其强大的交互性和直观性&#xff0c;在多个领域内得到了广泛应用。从农业生产的智能化管理到城市发展的精细化管理&#xff0c;再到企…

【软考】Redis不同的数据类型和应用场景。

Redis的不同数据类型和对应的应用场景&#xff1a; Redis 数据类型及其应用场景 String&#xff08;字符串&#xff09; 特点&#xff1a;简单的值存储&#xff0c;支持二进制数据。应用场景&#xff1a; 缓存用户会话。缓存小的配置文件。缓存计数器。文章浏览量&#xff0…