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

KafkaStream Local Store和Global Store区别和用法

前言

使用kafkaStream进行流式计算时,如果需要对数据进行状态处理,那么常用的会遇到kafkaStream的store,而store也有Local Store以及Global Store,当然也可以使用其他方案的来进行状态保存,文本主要理清楚kafkaStream中的Local Store以及Global Store之间的区别和用法,以及什么时候选择何种store和当store无法满足我们需求时,应该如何使用其他方案来进行数据的状态保存

本文所有方法和代码皆只针对kafka-streams的3.7.0版本,pom如下:

<dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-streams</artifactId><version>3.7.0</version>
</dependency>

由于不同版本的KafkaStream在使用上有较大区别,也因为KafkaStream不同版本API改动较大,所以如果版本不一致,使用方法甚至是一些核心概念都会跟本文讲述有所出入,并且KafkaStream由于相对小众,文档也很少,官网的文档也只是一些简单介绍,所以需要注意避坑

Local Store和Global Store的共同点和区别点
共同点:

1、都是用于流式计算中进行状态存储的

2、具体结构类似,使用的都是如:KeyValueStore,SessionStore等类

3、实际机制类似,会通过内存、本地目录和kafka Topic的变更记录等方式来进行缓存数据更新和恢复

不同点

1、适用场景不同

Local Store 适合用于单个实例的状态管理,适合处理单个分区的数据,并且缓存数据不会多个实例共享

Global Store 适用于跨实例共享数据状态,多个实例通过Topic中的更新记录来跟新进程中的数据

2、使用方法不同

Local Store 可以直接在代码中调用对应类型存储(如:KeyValueStore)的put方法进行更新数据,不需要考虑数据一致性(因为可见性只有单个实例)

Global Store 不能直接调用对应的put和delete方法,所有更新和删除缓存都需要通过发送数据到Global 配置的topic中,然后自行实现Topic数据消费者(实现:org.apache.kafka.streams.processor.api.Processor类),在消费者类中进行数据更新等操作,同时因为需要自己实现更新实例中的数据逻辑,数据一致性也需要开发者自行处理,虽然正常来说利用Kafka本身的特性很少出现数据一致性问题,但是如果多实例之间性能差异和网络环境等差异,容易将数据不一致的时长延长,如果要求Store一致性强且容忍数据不一致时限短,则需要注意考虑Store更新数据消费者的处理能力

3、扩展性

Local Store:可以通过增加输入主题的分区数来扩展处理能力,但每个实例仍然独立运行。

Global Store:需要在多个实例之间共享状态,因此在设计时需要考虑如何高效地管理和同步状态。

常见的Store 类型
org.apache.kafka.streams.state.KeyValueStore
org.apache.kafka.streams.state.SessionStore
org.apache.kafka.streams.state.TimestampedKeyValueStore
org.apache.kafka.streams.state.VersionedKeyValueStore
org.apache.kafka.streams.state.WindowStore

需要根据实际使用场景选择合适的状态存储类

用法
Local Store

第一步,先生成对应类型的StoreBuilder对象,如我需要用KeyValueStore,然后状态存储的名字是:testLocalStore(这个名字不能重复,因为会根据消费者id加储存名称创建对应的Topic,当然如果是不同的KafkaStream程序,消费者id不一致,那么重复就没有关系了),因为是KeyValue类型的储存,所以需要设定对应的Key和Value数据的序列化对象,具体代码如下:

StoreBuilder<KeyValueStore<String, String>> kvBuilder = Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore("testLocalStore"), Serdes.String(), Serdes.String());

其中Stores.persistentKeyValueStore代表的我得存储是持久化的,正常都是会用持久化,当然也有存储一些不重要或者程序重启丢失也无所谓的状态数据,可以使用Stores.inMemoryKeyValueStore以及基于LRU淘汰机制的储存Stores.lruMap,第二个参数Serdes.String()代表存储数据的key是字符串,第三个参数同理,如果是要存储一些对象,也可以使用自定义的序列化类,实现

org.apache.kafka.common.serialization.Serializer

序列化类,以及反序列化类

org.apache.kafka.common.serialization.Deserializer

然后定义好即可,如:

new Serdes.WrapperSerde<>(new KryoSerializer<>(TestStoreBean.class),new KryoDeserializer<>(TestStoreBean.class)

其中KryoSerializer和KryoDeserializer是我自定义的使用Kryo序列化Java对象的类,TestStoreBean是我保存的状态的数据封装bean

KryoSerializer代码如下:

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Output;
import org.apache.kafka.common.serialization.Serializer;import java.io.ByteArrayOutputStream;/*** kryo序列化类* @author Raye* @since 2024-6-4*/
public class KryoSerializer<T> implements Serializer<T> {private static final ThreadLocal<Kryo> KRYO_LOCAL = new ThreadLocal<Kryo>() {@Overrideprotected Kryo initialValue() {Kryo kryo = new Kryo();/*** 不要轻易改变这里的配置!更改之后,序列化的格式就会发生变化,* 上线的同时就必须清除 Redis 里的所有缓存,* 否则那些缓存再回来反序列化的时候,就会报错*///支持对象循环引用(否则会栈溢出)kryo.setReferences(true); //默认值就是 true,添加此行的目的是为了提醒维护者,不要改变这个配置//不强制要求注册类(注册行为无法保证多个 JVM 内同一个类的注册编号相同;而且业务系统中大量的 Class 也难以一一注册)kryo.setRegistrationRequired(false); //默认值就是 false,添加此行的目的是为了提醒维护者,不要改变这个配置return kryo;}};/*** 获得当前线程的 Kryo 实例** @return 当前线程的 Kryo 实例*/public static Kryo getInstance() {return KRYO_LOCAL.get();}private Class<T> clz;public KryoSerializer(Class<T> clz) {this.clz = clz;}@Overridepublic byte[] serialize(String s, T t) {if(t == null){return null;}ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();Output output = new Output(byteArrayOutputStream);Kryo kryo = getInstance();kryo.writeObjectOrNull(output, t,clz);output.flush();return byteArrayOutputStream.toByteArray();}
}

KryoDeserializer代码如下:

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import org.apache.kafka.common.serialization.Deserializer;import java.io.ByteArrayInputStream;/*** kryo反序列化类* @author Raye* @since 2024-6-4*/
public class KryoDeserializer<T> implements Deserializer<T> {private static final ThreadLocal<Kryo> KRYO_LOCAL = new ThreadLocal<Kryo>() {@Overrideprotected Kryo initialValue() {Kryo kryo = new Kryo();/*** 不要轻易改变这里的配置!更改之后,序列化的格式就会发生变化,* 上线的同时就必须清除 Redis 里的所有缓存,* 否则那些缓存再回来反序列化的时候,就会报错*///支持对象循环引用(否则会栈溢出)kryo.setReferences(true); //默认值就是 true,添加此行的目的是为了提醒维护者,不要改变这个配置//不强制要求注册类(注册行为无法保证多个 JVM 内同一个类的注册编号相同;而且业务系统中大量的 Class 也难以一一注册)kryo.setRegistrationRequired(false); //默认值就是 false,添加此行的目的是为了提醒维护者,不要改变这个配置return kryo;}};/*** 获得当前线程的 Kryo 实例** @return 当前线程的 Kryo 实例*/public static Kryo getInstance() {return KRYO_LOCAL.get();}private Class<T> clz;public KryoDeserializer(Class<T> clz) {this.clz = clz;}@Overridepublic T deserialize(String s, byte[] bytes) {if(bytes == null){return null;}ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);Input input = new Input(byteArrayInputStream);Kryo kryo = getInstance();try {return kryo.readObjectOrNull(input, clz);}catch (Exception e){e.printStackTrace();}return null;}
}

同理,使用LocalStore时,可以将代码替换成以下内容:

StoreBuilder<KeyValueStore<String, TestStoreBean>> kvBuilder = Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore("testLocalStore"), Serdes.String(), new Serdes.WrapperSerde<>(new KryoSerializer<>(TestStoreBean.class),new KryoDeserializer<>(TestStoreBean.class));

有了StoreBuilder对象之后,直接在StreamsBuilder对象中添加即可

streamsBuilder.addStateStore(kvBuilder);

需要使用时,先在处理数据的Processor类中的init方法获取对应的状态存储对象

this.testLocalStore = context.getStateStore("testLocalStore");

然后就可以在process方法中调用testLocalStore的get、put、delete等方法操作状态存储数据了,具体代码如下

	@Slf4jpublic static class StreamProcessor implements Processor<String,String,String,String> {private KeyValueStore<String,String> testLocalStore;private ProcessorContext context;private String toTopic;@Overridepublic void init(ProcessorContext context) {this.context = context;this.testLocalStore = context.getStateStore("testLocalStore");}public StreamProcessor(String toTopic) {this.toTopic = toTopic;}@Overridepublic void process(Record<String, String> record) {testLocalStore.put("key1","testValue1");log.info("testLocalStore key1 : {}",testLocalStore.get("key1"));testLocalStore.delete("key1");context.forward(record,toTopic);}}

其中实现的Processor类全称是:org.apache.kafka.streams.processor.api.Processor,上面代码只是在数据处理流程中简单保存了数据,然后获取出来以及删除,没有对流数据做任何处理,就直接发送到输出的topic了

完整代码如下:

	@Beanpublic KStream<String,String> kStreamTestStore(StreamsBuilder streamsBuilder){log.info("init kStreamTestStore");StoreBuilder<KeyValueStore<String, String>> kvBuilder = Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore("testLocalStore"), Serdes.String(), Serdes.String());streamsBuilder.addStateStore(kvBuilder);KStream<String, String> stream = streamsBuilder.stream(fromTopic);stream.process(()->new StreamProcessor(toTopic), Named.as(fromTopic),"testLocalStore");streamsBuilder.build().addSink(toTopic,toTopic,fromTopic);return stream;}

注意:由于使用Store需要通过ProcessorContext对象来获取Store对象,所以在KafkaStream常用的一些map,mapValue,flatMapValues这些流式计算方法中是没办法使用的,只能在一些更底层的Api中去使用,如process

Global Store

同Local Store一样,需要先生成对应类型的StoreBuilder对象,代码跟Local Store一样

StoreBuilder<KeyValueStore<String, String>> kvBuilder = Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore("testGlobalStore"), Serdes.String(), Serdes.String());

然后定义处理状态更新日志的Processor类,在这个类中,可以对缓存数据进行更新和删除操作(其他地方都是不能直接修改Global Store的)

public class GlobalStoreHandleProcessor<K, V> implements Processor<K,V,Void,Void> {private KeyValueStore<K, V> store;private String storeName;public GlobalStoreHandleProcessor(String storeName) {this.storeName = storeName;}@Overridepublic void process(Record<K,V> record) {if(record == null || record.value() == null) {return;}store.put(record.key(), record.value());}@Overridepublic void init(ProcessorContext context) {this.store = context.getStateStore(storeName);}}

跟KafkaStream的process是一样的,只需要在process方法中对缓存进行更新或者删除操作即可,我这里只是简单put操作,具体逻辑可以根据自己情况进行处理

在StreamsBuilder对象中添加StoreBuilder对象

streamsBuilder.addGlobalStore(kvBuilder,"testGlobalStore", Consumed.with(Serdes.String(),Serdes.String()),()->new GlobalStoreHandleProcessor<>("testGlobalStore"));

其中第二个参数testGlobalStore是Global Store绑定的数据变更记录的Topic,如果要更新,则需要通过向这个topic发送数据来进行更新Global Store中的数据

处理数据的Processor类实例代码

public static class StreamProcessor implements Processor<String,String,String,String> {private KeyValueStore<String,String> testGlobalStore;private ProcessorContext context;private String toTopic;@Overridepublic void init(ProcessorContext context) {this.context = context;this.testGlobalStore = context.getStateStore("testGlobalStore");}public StreamProcessor(String toTopic) {this.toTopic = toTopic;}@Overridepublic void process(Record<String, String> record) {testLocalStore.put(jsonObject.getString("key"),jsonObject.getString("value"));log.info("testLocalStore key1 : {}",testGlobalStore.get("key1"));//发送更新Global Store的数据context.forward(new Record("testGlobalKey","global value",record.timestamp()),"testGlobalStore");context.forward(record,toTopic);}}

与Local Store不同的是,不能在处理数据流的时候,对缓存进行put操作,只能通过将数据发送到Global Store关联的topic中,在GlobalStoreHandleProcessor中去做更新

完整代码如下:

	@Beanpublic KStream<String,String> kStreamTestStore(StreamsBuilder streamsBuilder){log.info("init kStreamTestStore");StoreBuilder<KeyValueStore<String, String>> kvBuilder = Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore("testGlobalStore"), Serdes.String(), Serdes.String());streamsBuilder.addGlobalStore(kvBuilder,"testGlobalStore", Consumed.with(Serdes.String(),Serdes.String()),()->new GlobalStoreHandleProcessor<>("testGlobalStore"));KStream<String, String> stream = streamsBuilder.stream(fromTopic);stream.process(()->new StreamProcessor(toTopic), Named.as(fromTopic));streamsBuilder.build().addSink(toTopic,toTopic,fromTopic);streamsBuilder.build().addSink("testGlobalStore","testGlobalStore",fromTopic);return stream;}

与Local Store不同点在于,不需要在process方法中添加store的名字,但是因为要从process方法中直接将更新Store的数据发送到topic,所以需要添加一个Global Store绑定的Topic的输出扩展,也就是下面这行代码

streamsBuilder.build().addSink("testGlobalStore","testGlobalStore",fromTopic);
不适合的场景

由于KafkaStream Store 没有自动过期数据和过期数据自动删除的概率(可能是有,但是我没有找到对应文档),所以如果我们存储的key集合特别大,并且需要自动过期和自动删除,那么就不适合使用Store来处理了,因为需要我们自行处理删除逻辑,尤其是有些场景中,并不会对过期的key进行访问,所以采用惰性删除基本上不现实,但是定时删除,因为Store会存储到磁盘,如果存储的key很多,删除对应数据的时候耗时很长,尤其是单次删除大量key的时候,可能会直接超时,并且还必须要自己处理定时删除的逻辑,想要更好的去删除,就需要大量时间去开发和优化。

虽然使用内存的Store能稍微好点,但是毕竟单个进程内存有限,并且正常流处理中,如果需要保存状态,那么肯定是希望进程重启之后,能恢复数据,避免计算出错的,所以如果是有大量不重复key,并且数据需要到期自动删除的话,可以直接使用Redis做状态存储,并且进过我得实际测试,使用Redis并不比Store慢,并且在key量越来越大的情况下,Redis的性能是完全优于Store的(只针对持久化的Store),当然使用Redis,还是会更使用Global Store一样,需要考虑数据一致性的问题,不过这个问题可以通过将相同key的数据从Kafka Topic就分配到同一个Topic分区中来避免

相关文章:

KafkaStream Local Store和Global Store区别和用法

前言 使用kafkaStream进行流式计算时&#xff0c;如果需要对数据进行状态处理&#xff0c;那么常用的会遇到kafkaStream的store&#xff0c;而store也有Local Store以及Global Store&#xff0c;当然也可以使用其他方案的来进行状态保存&#xff0c;文本主要理清楚kafkaStream…...

PowerDesigner导入Excel模板生成数据表

PowerDesigner导入Excel模板生成数据表 1.准备好需要导入的Excel表结构数据,模板内容如下图所示 2.打开PowerDesigner,新建一个physical data model文件,填入文件名称,选择数据库类型 3.点击Tools|Execute Commands|Edit/Run Script菜单或按下快捷键Ctrl Shift X打开脚本窗口…...

STM32 HAL库开发——入门篇(3):OLED、LCD

源自正点原子视频教程&#xff1a; 【正点原子】手把手教你学STM32 HAL库开发全集【真人出镜】STM32入门教学视频教程 单片机 嵌入式_哔哩哔哩_bilibili 一、OLED 二、内存保护&#xff08;MPU&#xff09;实验 2.1 内存保护单元 三、LCD 3.1 显示屏分类 3.2 LCD简介 3.3 LCD…...

在Linux中查找文件命令的几种方法

要在Linux中查找文件&#xff0c;可以使用以下几种不同的实现方法&#xff1a; 1. 使用find命令&#xff1a; find <搜索路径> <搜索选项> <搜索条件><搜索路径>&#xff1a;表示要搜索的起始路径&#xff0c;可以是一个具体的目录路径&#xff0c;也…...

【TB作品】MSP430F5529 单片机,温度控制系统,DS18B20,使用MSP430实现的智能温度控制系统

作品功能 这个智能温度控制系统基于MSP430单片机设计&#xff0c;能够实时监测环境温度并根据预设的温度报警值自动调节风扇和加热片的工作状态。主要功能包括&#xff1a; 实时显示当前温度。通过OLED屏幕显示温度报警值。通过按键设置温度报警值。实际温度超过报警值时&…...

立创小tips

立创小tips 原理图中 1-修改图纸属性 保存完&#xff0c;绘制原理图的界面就出现了&#xff0c;然后我们鼠标点击原理图的边缘变成红色就可以高边表格的属性了。 2-鼠标右键可以移动整个原理图 3-查看封装 点击任意一个元器件&#xff0c;在右侧就会显示封装属性&#xff…...

Html/HTML5常用标签的学习

课程目标 项目实战&#xff0c;肯定就需要静态网页。朝着做项目方式去学习静态网页。 01、编写第一个html工程结构化 cssjsimages/imgindex.html 归档存储和结构清晰就可以。 02、HTML标签分类 认知&#xff1a;标签为什么要分类&#xff0c;原因因为&#xff1a;分门别类…...

Tomcat 配置:一文掌握所有要点

引言 Apache Tomcat 是一个流行的开源 Java Servlet 容器和 Web 服务器&#xff0c;广泛用于开发和部署 Java Web 应用程序。正确配置 Tomcat 是确保其性能、安全性和稳定性的关键。本文将详细介绍 Tomcat 的各项配置&#xff0c;帮助您优化和管理 Tomcat 服务器。 一、Tomca…...

git 大文件上传失败 Please remove the file from history and try again.

根据提示执行命令 --- 查找到当前文件 git rev-list --objects --all | grep b24e74b34e7d482e2bc687e017c8ab28cd1d24b6git filter-branch --tree-filter rm -f 文件名 --tag-name-filter cat -- --all git push origin --tags --force git push origin --all --force...

骑砍2霸主MOD开发(14)-进击的巨人

一.巨人 sbyte boneIndex Skeleton.GetBoneIndexFromName(Mission.MainAgent.AgentVisuals.GetSkeleton().GetName(), "r_hand"); cp Mission.MainAgent.AgentVisuals.AddPrefabToAgentVisualBoneByRealBoneIndex("p_sword_a", boneIndex); float agent…...

Android 可拖拽的View,限制在父布局中随意拖拽;拖拽结束后可左右吸边;

实现方法一&#xff1a;自定义View 可随意拖动拖拽的View&#xff0c;限制拖动范围是父布局中&#xff1b; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.ViewGroup; …...

逐步更新动画混合参数(Blend)使其平滑地过渡到目标值

1.具体实现 逐步更新一个动画混合参数&#xff08;Blend&#xff09;&#xff0c;使其平滑地过渡到目标值&#xff0c;可以实现角色动作的平滑过渡&#xff0c;比如从走路过渡到跑步。 private float currentBleng;private float targetBlend;public float accelerSpeed 5;//…...

【多模态/CV】图像数据增强数据分析和处理

note 多模态大模型训练前&#xff0c;图片数据处理的常见操作&#xff1a;分辨率调整、网格畸变、水平翻转、分辨率调整、随机crop、换颜色、多张图片拼接、相似图片检测并去重等 一、分辨率调整 from PIL import Image def resize_image(original_image_path, save_image_p…...

代码随想录——修建二叉搜素树(Leetcode669)

题目链接 递归 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) {* …...

EasyExcel导出多个sheet封装

导出多个sheet 在需求中&#xff0c;会有需要导出多种sheet的情况&#xff0c;那么这里使用easyexcel进行整合 步骤 1、导入依赖 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><d…...

【Python错误】:AttributeError: ‘generator‘ object has no attribute ‘next‘解决办法

【Python错误】&#xff1a;AttributeError: ‘generator’ object has no attribute next’解决办法 在Python中&#xff0c;生成器是一种使用yield语句的特殊迭代器&#xff0c;它允许你在函数中产生一个值序列&#xff0c;而无需一次性创建并返回整个列表。然而&#xff0c;…...

如何配置Feign以实现服务调试

1、引入依赖 在项目中&#xff0c;需要引入Spring Cloud OpenFeign的依赖。这通常是通过在pom.xml文件中添加相应的Maven依赖来完成的。例如&#xff1a; <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starte…...

pc之间的相互通信详解

如图&#xff0c;实现两台pc之间的相互通信 1.pc1和pc2之间如何进行通讯。 2.pc有mac和ip&#xff0c;首先pc1需要向sw1发送广播&#xff0c;sw1查询mac地址表&#xff0c;向router发送广播&#xff0c;router不接受广播&#xff0c;router的每个接口都有ip和mac&#xff0c;…...

Mongodb中字段的删除

学习mongodb&#xff0c;体会mongodb的每一个使用细节&#xff0c;欢迎阅读威赞的文章。这是威赞发布的第61篇mongodb技术文章&#xff0c;欢迎浏览本专栏威赞发布的其他文章。 本篇文章&#xff0c;探讨UPDATE中的操作符$unset。Mongodb数据插入后&#xff0c;开发人员使用$u…...

TP8 PHP 动态变量调用 (new $class())->$action($data)

动态&#xff1a; $class \app\table\model\Log; $action DataSave; $data [...]; // 假设这是你要保存的数据//class_exists和method_exists的检查&#xff0c;这段代码能够在尝试实例化类或调用方法之前&#xff0c;先验证类是否存在以及该类中是否存在指定的方法。如果类…...

理解JVM内存模型与Java内存模型(JMM)

理解JVM内存模型与Java内存模型&#xff08;JMM&#xff09; 在Java程序的运行过程中&#xff0c;内存管理和线程的同步是两个重要的概念。本文将深入探讨JVM内存模型&#xff08;Java Virtual Machine Memory Model&#xff09;和JMM&#xff08;Java Memory Model&#xff0…...

鸿蒙OS初识

学习官网&#xff1a;https://www.harmonyos.com/cn/develop 准备 注册&#xff0c;安装软件&#xff08;node:12, DevEco Studio&#xff09;&#xff1a; https://developer.harmonyos.com/cn/docs/documentation/doc-guides/software_install-0000001053582415#ZH-CN_TOP…...

发布自己的 npm 插件包:步骤与最佳实践

在 Node.js 的生态系统中&#xff0c;npm&#xff08;Node Package Manager&#xff09;是一个不可或缺的组成部分。npm 允许开发者创建、共享和使用各种库和插件。如果你有自己的 Node.js 插件或库&#xff0c;并且希望与全世界的其他开发者共享&#xff0c;那么发布到 npm 是…...

BubbleML: A Multiphase Multiphysics Dataset and Benchmarks for Machine Learning

我们使用以下六个分类标准: 研究方法: 这个标准根据如何收集和分析数据来区分研究方法。 实验研究,如参考文献[64]中的研究,涉及在受控环境中研究人员操纵变量并观察结果的物理实验。这种方法对于收集真实世界的数据很有价值,但可能成本高且耗时。模拟研究利用计算模型来模…...

vscode+latex设置跳转快捷键

安装参考 https://blog.csdn.net/Hacker_MAI/article/details/130334821 设置默认recipe ctrl P 打开设置&#xff0c;搜索recipe 也可以点这里看看有哪些配置 2 设置跳转快捷键...

PHP序列化、反序列化

目录 一、PHP序列化&#xff1a;serialize() 1.对象序列化 2.pop链序列化 3.数组序列化 二、反序列化&#xff1a;unserialize() 三、魔术方法 ​四、NSSCTF相关简单题目 1.[SWPUCTF 2021 新生赛]ez_unserialize 2.[SWPUCTF 2021 新生赛]no_wakeup 学习参考&#xff1…...

websocket链接携带参数

前端创建链接时官方提供的构造函数 var aWebSocket new WebSocket(url, [protocols]); url&#xff1a;要连接的URL&#xff1b;这应该是WebSocket服务器将响应的URL。 protocols&#xff1a;可选&#xff1b;一个协议字符串或者一个包含协议字符串的数组。这些字符串用于指定…...

【C++进阶】深入STL之list:模拟实现深入理解List与迭代器

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;初步了解 list &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀STL之list &#x1f4d2;1. list…...

技术管理之巅—如何从零打造高质效互联网技术团队阅读体验

技术管理之巅—如何从零打造高质效互联网技术团队 《技术管理之巅&#xff1a;如何从零打造高质效互联网技术团队》是黄哲铿所著的一本书&#xff0c;致力于帮助技术管理者从零开始打造高效的互联网技术团队。该书分为多个章节&#xff0c;分别探讨了从团队文化建设到技术架构…...

机器学习与数据挖掘知识点总结(一)

简介&#xff1a;随着人工智能&#xff08;AI&#xff09;蓬勃发展&#xff0c;也有越来越多的人涌入到这一行业。下面简单介绍一下机器学习的各大领域&#xff0c;机器学习包含深度学习以及强化学习&#xff0c;在本节的机器学习中主要阐述一下机器学习的线性回归逻辑回归&…...

经典的java做网站/电商seo是什么

title: 刷题遇上的知识点 date: 2016-05-27 13:36:36 categories: C tags: - C 1 运算符号|&#xff08;按位取或运算&#xff09; 和&&#xff08;按位取与运算&#xff09;&#xff0c;逗号运算符 例题分析&#xff1a; 如果x2014&#xff0c;下面函数的返回值是&a…...

烟台优化网站排名/网页制作与设计教程

学习操作系统时&#xff0c;我们知道CUP处理事务的时候有个中断机制&#xff0c;以便进行事务的切换&#xff0c;中断处理的过程&#xff1a; 1)唤醒被阻塞的驱动(程序)进程&#xff1b;2)保护被中断的CPU环境&#xff1b;3)转入响应的设备处理程序&#xff1b;4)中断处理&…...

清风算法受影响的网站/在线bt种子

今天在部署项目时&#xff0c;遇到项目组其它人重整了server上的iis。结果外部訪问不了所部属的项目&#xff0c;通过一些渠道找到了设置方法 例如以下报错的截图&#xff1a; 原因是“入站ICMP规则”被重整了&#xff0c;所以我们须要又一次新建入站ICMP规则 &#xff08;详…...

要制作自己的网站需要什么材料/网站统计数据分析

原创不易&#xff0c;转载前请注明博主的链接地址&#xff1a;Blessy_Zhu https://blog.csdn.net/weixin_42555080  一 从机器学习到深度学习 我们知道&#xff0c;Machine Learning分为两大派别&#xff1a;频率派和贝叶斯派&#xff1b;前者逐渐发展为统计学习&#xff0c;…...

专业科技网站建设/百度框架户开户渠道

vi的使用--使用vi查找和替换 vi提供了几种定位查找一个指定的字符串在文件中位置的方法。同时还提供一种功能强大的全局替换功能。 1. 查找一个字符串 一个字符串是一行上的一个或几个字符。 为查找一个字符串&#xff0c;在vi命令模式下键入“/”&#xff0c;后面跟要查找的…...

网站程序调试模式怎么做/sq网站推广

方法一(此方法支持 select 语句&#xff0c;insert,delect,update不支持) &#xff1a;  $sql DB::table(my_table)->select()->tosql();方法二(此方法支持 select 语句&#xff0c;insert,delect,update不支持) &#xff1a; DB::connection()->enableQueryLog(); …...