Kafka 保证多分区的全局顺序性的设计方案和具体实现
Kafka 本身无法直接保证多分区的全局顺序性,因为分区设计旨在并行处理以提升吞吐量。
要实现多分区的顺序性,可尝试通过以下方法在系统层面或业务逻辑上解决:
一、方案设计
-
单一分区路由(还是将消息发送到同一分区):
- 将所有需要顺序的消息通过相同的分区键(Partition Key)路由到同一个分区,Kafka 会保证该分区内消息的顺序性。
- 实现方式:在生产消息时指定一致的 key(如固定值或业务相关标识),确保消息哈希到同一分区。
- 局限:牺牲并行性,单一分区可能成为性能瓶颈。
-
外部排序机制:
- 允许消息分散到多分区,在消费者端通过缓冲和排序恢复全局顺序。
- 实现方式:
- 为每条消息添加时间戳或序列号。
- 消费者收集所有分区的消息,存入缓冲区,按时间戳或序列号排序后再处理。
- 工具:可以使用内存队列(如 Java 的 PriorityQueue)或外部存储(如 Redis)实现排序。
- 局限:增加消费者复杂性和延迟,需处理缓冲区溢出或数据丢失情况。
-
Kafka Streams 或自定义处理:
- 使用 Kafka Streams 或其他流处理框架(如 Flink、Spark)处理多分区消息。
- 实现方式:
- 通过窗口操作(windowing)或状态存储(state store)收集多分区消息。
- 按业务逻辑(如时间戳或事件 ID)重新排序后输出到新主题。
- 局限:需要额外计算资源,适合复杂流处理场景。
-
主题级顺序控制:
- 将多分区主题的数据汇总到单一分区的新主题。
- 实现方式:
- 消费者从多分区读取消息,写入到Kafka的单一分区主题(需序列号或时间戳)。
- 后续消费者从单一分区主题读取,获取有序消息。
- 局限:增加额外主题和处理步骤,可能引入延迟。
-
事务与自定义分区器:
- 结合 Kafka 事务和自定义分区器(Custom Partitioner)控制消息分配。
- 实现方式:
- 自定义分区器根据业务逻辑(如时间窗口或事件类型)动态分配分区。
- 使用事务确保跨分区写入的原子性,消费者通过
read_committed
读取。 - 在消费者端按需排序。
- 局限:实现复杂,事务增加开销。
建议与权衡
- 适用场景:单一分区路由适合简单场景;外部排序或流处理适合高吞吐量但需全局顺序的复杂场景。
- 性能考量:多分区顺序性通常以延迟或资源为代价,需评估业务对顺序性和吞吐量的优先级。
- 监控与测试:实现后需监控分区负载、消费者延迟,确保系统稳定。
二、实现过程
每个方案包括较为详细的设计思路、操作步骤和简单的代码实现,基于 Java并考虑生产环境的可扩展性和稳定性。
方案 1:单一分区路由
设计思路:
- 通过一致的分区键将需要顺序的消息路由到同一分区,利用 Kafka 分区内顺序性。
- 适合简单场景,如按用户 ID 或订单 ID 保证顺序。
操作流程:
- 配置 Kafka 生产者,指定分区键。
- 生产者发送消息时为每条消息设置相同的 key。
- 消费者从指定分区读取消息,天然有序。
- 监控单一分区负载,必要时调整分区数或优化消费者处理能力。
代码示例:
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 SinglePartitionProducer {public static void main(String[] args) {// 配置生产者Properties props = new Properties();props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());props.put(ProducerConfig.ACKS_CONFIG, "all"); // 确保一致性KafkaProducer<String, String> producer = new KafkaProducer<>(props);String topic = "ordered-topic";// 发送消息,固定分区键String fixedKey = "order-group-1"; // 所有消息使用相同 key 路由到同一分区for (int i = 0; i < 100; i++) {String message = "Message-" + i;ProducerRecord<String, String> record = new ProducerRecord<>(topic, fixedKey, message);producer.send(record, (metadata, exception) -> {if (exception == null) {System.out.printf("发送到 partition %d, offset %d%n", metadata.partition(), metadata.offset());} else {exception.printStackTrace();}});}producer.close();}
}
生产注意事项:
- 分区数:主题分区数需根据负载调整,避免单一分区过载。
- 监控:使用 Kafka 监控工具(如 Burrow 或 Kafka Manager)检查分区延迟和消费者 lag。
- 扩展性:若负载增加,可通过增加消费者组实例提高处理能力。
方案 2:外部排序机制
设计思路:
- 消息分散到多分区,消费者收集消息后通过时间戳或序列号排序。
- 使用内存缓冲(如 PriorityQueue)或外部存储(如 Redis)实现排序。
操作流程:
- 生产者为每条消息附加时间戳或序列号。
- 消费者并行读取多分区消息,存入排序缓冲区。
- 按时间戳或序列号排序后处理消息。
- 配置重试机制和异常处理,确保数据不丢失。
代码示例:
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringDeserializer;import java.time.Duration;
import java.util.*;
import java.util.concurrent.PriorityQueue;public class ExternalSortingConsumer {static class Message implements Comparable<Message> {String value;long timestamp;Message(String value, long timestamp) {this.value = value;this.timestamp = timestamp;}@Overridepublic int compareTo(Message other) {return Long.compare(this.timestamp, other.timestamp);}}public static void main(String[] args) {// 配置消费者Properties props = new Properties();props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");props.put(ConsumerConfig.GROUP_ID_CONFIG, "sorting-consumer-group");props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);consumer.subscribe(Collections.singletonList("multi-partition-topic"));// 使用 PriorityQueue 按时间戳排序PriorityQueue<Message> buffer = new PriorityQueue<>();long lastProcessedTimestamp = 0;while (true) {ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));for (ConsumerRecord<String, String> record : records) {// 假设消息格式为 "message|timestamp"String[] parts = record.value().split("\\|");String message = parts[0];long timestamp = Long.parseLong(parts[1]);buffer.offer(new Message(message, timestamp));}// 处理排序后的消息while (!buffer.isEmpty() && buffer.peek().timestamp <= lastProcessedTimestamp + 1000) {Message msg = buffer.poll();System.out.println("消息: " + msg.value + " 时间戳: " + msg.timestamp);lastProcessedTimestamp = msg.timestamp;}// 手动提交偏移量consumer.commitSync();}}
}
生产注意事项:
- 缓冲区管理:需设置缓冲区大小上限,防止内存溢出。
- 时间戳一致性:生产者需使用高精度时间戳(如 System.currentTimeMillis())。
- 分布式场景:若消费者组有多个实例,需使用分布式存储(如 Redis)协调排序。
方案 3:Kafka Streams 排序
设计思路:
- 使用 Kafka Streams 收集多分区消息,通过状态存储和窗口操作排序。
- 输出到新主题,供下游消费者读取有序消息。
操作流程:
- 配置 Kafka Streams 应用,定义输入和输出主题。
- 收集多分区消息,按时间戳分组并排序。
- 将排序结果写入单一分区主题。
- 部署 Streams 应用,监控状态存储和性能。
代码示例:
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KafkaStreams;
import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.StreamsConfig;
import org.apache.kafka.streams.kstream.KStream;
import org.apache.kafka.streams.state.KeyValueStore;
import org.apache.kafka.streams.processor.Transformer;
import org.apache.kafka.streams.state.StoreBuilder;
import org.apache.kafka.streams.state.Stores;
import org.apache.kafka.streams.processor.ProcessorContext;
import org.apache.kafka.streams.KeyValue;import java.util.Properties;
import java.util.TreeSet;public class KafkaStreamsSorter {public static void main(String[] args) {// 配置 StreamsProperties props = new Properties();props.put(StreamsConfig.APPLICATION_ID_CONFIG, "streams-sorter");props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");props.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());StreamsBuilder builder = new StreamsBuilder();// 定义状态存储StoreBuilder<KeyValueStore<String, String>> storeBuilder = Stores.keyValueStoreBuilder(Stores.persistentKeyValueStore("sorting-store"),Serdes.String(), Serdes.String());builder.addStateStore(storeBuilder);// 读取输入主题KStream<String, String> input = builder.stream("multi-partition-topic");// 按时间戳排序并输出input.transform(() -> new SortingTransformer(), "sorting-store").to("ordered-output-topic");KafkaStreams streams = new KafkaStreams(builder.build(), props);streams.start();Runtime.getRuntime().addShutdownHook(new Thread(streams::close));}static class SortingTransformer implements Transformer<String, String, KeyValue<String, String>> {private KeyValueStore<String, String> store;private TreeSet<String> sortedMessages;@Overridepublic void init(ProcessorContext context) {this.store = context.getStateStore("sorting-store");this.sortedMessages = new TreeSet<>((a, b) -> {long t1 = Long.parseLong(a.split("\\|")[1]);long t2 = Long.parseLong(b.split("\\|")[1]);return Long.compare(t1, t2);});}@Overridepublic KeyValue<String, String> transform(String key, String value) {sortedMessages.add(value);if (sortedMessages.size() >= 100) { // 批量处理String oldest = sortedMessages.pollFirst();return KeyValue.pair(key, oldest);}return null;}@Overridepublic void close() {}}
}
生产注意事项:
- 状态存储:确保状态存储持久化,防止故障丢失。
- 性能优化:调整窗口大小和批处理阈值,平衡延迟和吞吐量。
- 部署:使用多实例部署 Streams 应用,提高容错性。
方案 4:主题级顺序控制
设计思路:
- 多分区消息汇总到单一分区主题,消费者从单一分区读取有序消息。
- 生产者附加序列号,消费者按序列号处理。
操作流程:
- 配置生产者为消息附加序列号。
- 消费者读取多分区消息,写入单一分区主题。
- 下游消费者从单一分区主题读取有序消息。
- 监控主题负载和偏移量,确保数据一致性。
代码示例:
import org.apache.kafka.clients.consumer.*;
import org.apache.kafka.clients.producer.*;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.apache.kafka.common.serialization.StringSerializer;import java.time.Duration;
import java.util.Collections;
import java.util.Properties;public class TopicLevelOrdering {public static void main(String[] args) {// 生产者配置Properties producerProps = new Properties();producerProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");producerProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());producerProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());KafkaProducer<String, String> producer = new KafkaProducer<>(producerProps);// 消费者配置Properties consumerProps = new Properties();consumerProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");consumerProps.put(ConsumerConfig.GROUP_ID_CONFIG, "ordering-group");consumerProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());consumerProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());consumerProps.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");KafkaConsumer<String, String> consumer = new KafkaConsumer<>(consumerProps);consumer.subscribe(Collections.singletonList("multi-partition-topic"));String outputTopic = "single-partition-topic";while (true) {ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));for (ConsumerRecord<String, String> record : records) {// 假设消息包含序列号ProducerRecord<String, String> newRecord = new ProducerRecord<>(outputTopic, null, record.value());producer.send(newRecord, (metadata, exception) -> {if (exception != null) {exception.printStackTrace();}});}consumer.commitSync();}}
}
生产注意事项:
- 单一分区主题:确保输出主题只有一个分区。
- 序列号:生产者需为消息附加唯一序列号,防止重复或遗漏。
- 一致性:使用事务确保写入单一分区主题的原子性。
总结与生产部署建议
- 单一分区路由:简单易实现,适合低吞吐量场景。
- 外部排序:适合需要高吞吐量但全局顺序的场景,需关注缓冲区管理。
- Kafka Streams:适合复杂流处理,需额外计算资源。
- 主题级顺序控制:折衷方案,适合已有单一分区主题的系统。
- 通用建议:
- 使用 Kafka 监控工具(如 Prometheus + Grafana)跟踪分区负载、延迟和消费者 lag。
- 配置重试机制和死信队列(DLQ)处理异常消息。
- 定期测试故障恢复,确保顺序性和一致性。
相关文章:
Kafka 保证多分区的全局顺序性的设计方案和具体实现
Kafka 本身无法直接保证多分区的全局顺序性,因为分区设计旨在并行处理以提升吞吐量。 要实现多分区的顺序性,可尝试通过以下方法在系统层面或业务逻辑上解决: 一、方案设计 单一分区路由(还是将消息发送到同一分区)&a…...
数据结构初阶:二叉树(四)
概述:本篇博客主要介绍链式结构二叉树的实现。 目录 1.实现链式结构二叉树 1.1 二叉树的头文件(tree.h) 1.2 创建二叉树 1.3 前中后序遍历 1.3.1 遍历规则 1.3.1.1 前序遍历代码实现 1.3.1.2 中序遍历代码实现 1.3.1.3 后序遍历代…...
华为开发岗暑期实习笔试(2025年4月16日)
刷题小记: 第一题怀疑测试样例不完整,贪心法不应该能够解决该题。第二题使用0-1BFS解决单源最短路径的问题,往往搭配双端队列实现。第三题是运用动态规划解决最大不重叠子区间个数的问题,难点在于满足3重判断规则,所需…...
第一篇:Django简介
第一篇:Django简介 文章目录 第一篇:Django简介一、纯手写一个简易版的web框架1、软件开发架构2、HTTP协议3、简易的socket服务端4、wsgiref模块5、动静态网页6、后端获取当前时间展示到html页面上7、字典数据传给html文件8、数据从数据库中获取的展示到…...
2025年渗透测试面试题总结-拷打题库13(题目+回答)
网络安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 2025年渗透测试面试题总结-拷打题库13 一、GitHub等三方敏感信息泄漏防御 二、业务逻辑漏洞技术规避 …...
(09)Vue脚手架的使用(Vite、vue-cli、create-vue)
本系列教程目录:Vue3Element Plus全套学习笔记-目录大纲 文章目录 第3章 Vue脚手架3.1 vite3.3.1 Vite使用1)创建Vite项目2)Vite项目打包 3.1.2 组件化开发3.1.4 Vite工程运行原理1)分析main.js2)自定义根组件 3.2 vue…...
Unity 将Excel表格中的数据导入到Mysql数据表中
1.Mysql数据表users如下: 2.即将导入的Excel表格如下: 3.代码如下: using System; using System.Data; using System.IO; using Excel; using MySql.Data.MySqlClient; using UnityEngine; using UnityEditor;public class ImportExcel {// …...
【QT】信号与槽中多个按钮(pushbutton)共用一个槽函数的两种实现方式
两种方法的对比 方法1:sender() 优点:代码简洁,无需额外参数 缺点:依赖运行时类型转换,安全性较低 适用场景:简单场景,少量按钮 方法2:Lambda (推荐) 优点:安全直观&…...
Python----深度学习(神经网络的过拟合解决方案)
一、正则化 1.1、正则化 正则化是一种用于控制模型复杂度的技术。它通过在损失函数中添加额外的项(正则 化项)来降低模型的复杂度,以防止过拟合。 在机器学习中,模型的目标是在训练数据上获得较好的拟合效果。然而,过…...
【金仓数据库征文】从 HTAP 到 AI 加速,KingbaseES 的未来之路
国产数据库早已实现 “可替代”,但要真正与国际头部厂商掰手腕,必须在 HTAP(Hybrid‑Transaction/Analytical Processing)与 AI 加速 两条技术赛道上实现跨越。KingbaseES 自 V8R3 调整为多进程架构后,历经 V8R6、KSOn…...
创建第一个Spring Boot项目
什么是Spring Boot 随着Spring的快速发展,项目中的XML文件越来越多,繁琐的配置以及,整合第三方框架的配置问题,导致大大增加了开发和部署的效率,使开发者无法专心于业务的开发。Spring Boot就相当于使Spring框架的脚手…...
Java—— 正则表达式 练习
需求: 请编写正则表达式验证用户输入的手机号码是否满足要求。 请编写正则表达式验证用户输入的邮箱号是否满足要求。 请编写正则表达式验证用户输入的电话号码是否满足要求。 验证手机号码 13112345678 13712345667 13945679027 139456790271 验证座机电话号码 02…...
Linux[指令与权限]
Linux指令与权限 Linux环境中,打包文件有多种 tar (打包/解包) 指令 tar -czvf 文件要打包到的位置 文件(打包并压缩到) tar -xzvf 文件(在当前目录下解压) tar选项 -c创建压缩文件 -z使用gzip属性压缩 -v展现压缩过程 -f后面使用新建文档名 -x不要新建,解压 -C 文件…...
MySQL数据库精研之旅第十期:打造高效联合查询的实战宝典
专栏:MySQL数据库成长记 个人主页:手握风云 目录 一、简介 1.1. 为什么要使用联合查询 1.2. 多表联合查询时的计算 1.3. 示例 二、内连接 2.1. 语法 2.2. 示例 三、外连接 4.1. 语法 4.2. 示例 一、简介 1.1. 为什么要使用联合查询 一次查询需…...
【Redis】集合类型Set 常用命令详解
1. sadd - 添加 语法:sadd key value > sadd testset A 1 > sadd testset B 1 > sadd testset C 1 > sadd testset C # set的值不能重复 0 > smembers set1 # 查询指定set的所有值,乱序 1) "B" 2) "A" 3) "C&qu…...
React 5 种组件提取思路与实践
在开发时,经常遇到一些高度重复但略有差异的 UI 模式,此时我们当然会把组件提取出去,但是组件提取的方式有很多,怎么根据不同场景选取合适的方式呢?尤其时在复杂的业务场景中,组件提取的思路影响着着代码的可维护性、可读性以及扩展性。本文将以一个[详情]组件为例,探讨…...
第十五届蓝桥杯 2024 C/C++组 合法密码
目录 题目: 题目描述: 题目链接: 思路: substr函数: 思路详解: 代码: 代码详解; 题目: 题目描述: 题目链接: P10906 [蓝桥杯 2024 国 B] 合法密码 -…...
云原生时代的双轮驱动
在当今数字化浪潮汹涌澎湃的时代,企业 IT 主管、CIO、CTO 们肩负着引领企业乘风破浪、实现数字化转型的重任。而主数据平台与数据中台,宛如企业数字化征程中的双引擎,为企业发展注入强劲动力。 一、主数据与数据中台:企业数据世界…...
GD32F407单片机开发入门(六)定时器TIMER详解及实战含源码
文章目录 一.概要二.通用定时器内部结构1.时基单元2.时钟源3.输入捕获4.输出比较 三.通用定时器内部特色四.TIME定时器1ms中断例程五.工程源代码下载六.小结 一.概要 定时器就是计数器,应用在我们生活的方方面面,比如有闹钟、计时器等。在GD32F407VET6定…...
时序数据库 TDengine 助力石油石化业务, 平滑接替 Oracle 数据库
小T导读:胜软科技在石油石化行业中选择使用 TDengine 处理时序数据,不仅显著降低了运维数据库的成本,也大幅减少了存储空间的占用,实现了从原有的 40 多套 Oracle 数据库向仅 9 套 TDengine集群的精简替换。在迁移过程中ÿ…...
【问题解决】本机navicat连接云服务器mysql
一般情况下,当你使用navicat等工具连接云服务器会因为mysql的安全机制,导致无法连接root用户,但是在测试环境中,不考虑安全性的前提条件下,可以通过修改MySQL的配置文件来连接云服务器mysql的root用户。 选择数据库&am…...
STM32F407 的通用定时器与串口配置深度解析
在 STM32F407 芯片的开发过程中,通用定时器和串口的配置与使用是极为关键的技能点。本文将结合提供的代码示例,深入剖析这两个模块的配置流程、工作原理以及实际应用,助力开发者更好地掌握相关技术。 一、通用定时器 (一&#x…...
深入探究Linux项目自动化构建工具:make与Makefile
目录 引言 一、make与Makefile概述 1.1 背景 1.2 理解 二、make工作原理 2.1 查找Makefile 2.2 确定目标文件 2.3 处理文件依赖 三、Makefile实例分析 3.1 简单C程序示例 3.2 项目清理机制 四、结合行缓冲区概念的有趣现象 五、结语 引言 在Linux软件开发的世界里…...
【Hive入门】Hive基础操作与SQL语法:DDL操作全面指南
目录 1 Hive DDL操作概述 2 数据库操作全流程 2.1 创建数据库 2.2 查看数据库 2.3 使用数据库 2.4 修改数据库 2.5 删除数据库 3 表操作全流程 3.1 创建表 3.2 查看表信息 3.3 修改表 3.4 删除表 4 分区与分桶操作 4.1 分区操作流程 4.2 分桶操作 5 最佳实践与…...
STM32F103 “BluePill” 上的 DMA 原理与实践
摘要:本文深入浅出地介绍什么是 DMA(直接存储器访问),它的核心原理、硬件架构,以及在 STM32F103(BluePill)上常见的几种使用场景(ADC、UART、内存拷贝等)。通过对比 CPU 轮询、中断、DMA 三种方式的数据搬运效率,结合寄存器级和 HAL 库示例代码,并附带性能测试与优化…...
软考软件设计师30天备考指南
文章目录 一、考情分析(一)综合知识(二)案例分析 二、30天学习规划(一)第1 - 5天:基础夯实(二)第6 - 10天:核心知识突破(三)第11 - 15…...
比较:AWS VPC peering与 AWS Transit Gateway
简述: VPC 对等连接和 Transit Gateway 用于连接多个 VPC。VPC 对等连接提供全网状架构,而 Transit Gateway 提供中心辐射型架构。Transit Gateway 提供大规模 VPC 连接,并简化了 VPC 间通信管理,相比 VPC 对等连接,支持大量 VPC 的 VPC 间通信管理。 VPC 对等连接 AWS V…...
【AI大模型】MCP:AI应用的“超级扩展坞”
一、什么是MCP MCP(Model Context Protocol,模型上下文协议)是一种新兴的开放协议,于2024年11月由Anthropic公司(Claude的开发者)开源。它的核心目标是建立一个类似USB-C的标准化协议,统一AI模…...
线程封装
目录 makefile Thread.hpp main.cc 以面向对象的方式造轮子 #ifndef _THREAD_HPP__ // 如果没有定义过 _THREAD_HPP__ #define _THREAD_HPP__ // 则定义 _THREAD_HPP__// 这里是头文件的实际内容(类、函数声明等)#endif // 结束条件…...
【Java后端】MyBatis 与 MyBatis-Plus 如何防止 SQL 注入?从原理到实战
在日常开发中,SQL 注入是一种常见但危害巨大的安全漏洞。如果你正在使用 MyBatis 或 MyBatis-Plus 进行数据库操作,这篇文章将带你系统了解:这两个框架是如何防止 SQL 注入的,我们又该如何写出安全的代码。 什么是 SQL 注入&#…...
智能穿戴的终极形态会是AR眼镜吗?
清晨的地铁里,戴着普通眼镜的小张正通过镜片查看实时导航路线,眼前的虚拟箭头精准指引换乘方向;手术室里,主刀医生透过镜片看到患者血管的3D投影,如同获得透视眼般精准避开危险区域;装修现场,设…...
ubantu18.04(Hadoop3.1.3)Hive3.1.2安装指南
说明:本文图片较多,耐心等待加载。(建议用电脑) 注意所有打开的文件都要记得保存。本文的操作均在Master主机下进行 第一步:准备工作 本文是在之前Hadoop搭建完集群环境后继续进行的,因此需要读者完成我之…...
Hive 多表查询案例
文章目录 前提条件Hive 多表查询案例JOIN案例JOIN查询数据准备1. 内连接(INNER JOIN)2. 左外连接(LEFT OUTER JOIN)3. 右外连接(RIGHT OUTER JOIN)4. 全外连接(FULL OUTER JOIN)5. 多…...
4.23刷题记录(栈与队列专题)
第一部分:基础知识 栈先进后出,队列先进先出栈用stack实现,主要函数有pop,push,top队列由queue或者deque实现,主要函数有front,back,push,pop,emplace&#…...
Python常用的第三方模块之【jieba库】支持三种分词模式:精确模式、全模式和搜索引擎模式(提高召回率)
Jieba 是一个流行的中文分词Python库,它提供了三种分词模式:精确模式、全模式和搜索引擎模式。精确模式尝试将句子最精确地切分,适合文本分析;全模式则扫描文本中所有可能的词语,速度快但存在冗余;搜索引擎…...
Redisson实战:分布式系统中的五大典型应用场景
引言 在分布式系统架构中,数据一致性、高并发控制和资源协调是开发者面临的核心挑战。Redisson作为基于Redis的Java客户端,不仅提供了丰富的分布式对象和服务,还简化了分布式场景下的编程模型。本文将通过实际代码示例,解析Redis…...
webrtc建立连接的过程
WebRTC 连接全过程:从零到视频通话的每一步 WebRTC 是个神奇的技术,让浏览器直接进行点对点(P2P)音视频通话或数据传输,不用每次都靠服务器中转。想知道 Alice 和 Bob 是怎么通过 WebRTC 建立视频通话的吗?…...
system verilog 语句 耗时规则
在 SystemVerilog 中,确实有一类语句是**不消耗仿真时间(zero simulation time)**的,我们一般叫它们: ✅ 零延迟语句(Zero-Time Statements) 🔹1. 什么是“不费时间”的语句? 这些语句在仿真时…...
【Docker】在Ubuntu平台上的安装部署
写在前面 docker作为一种部署项目的辅助工具,真是太好用了需要魔法,不然无法正常运行笔者环境:ubuntu22.04 具体步骤 更新系统包索引 sudo apt update安装必要依赖包 sudo apt install -y apt-transport-https ca-certificates curl softwa…...
2025年阅读论文的常用工具推荐
在快速发展的学术界,阅读和整理论文的能力对于研究者和学生来说至关重要。随着科技的进步,各种工具应运而生,帮助我们更高效地处理文献。本文将为您推荐一些2025年最常用的阅读论文工具,让您的学术之路更加顺畅。 1. SumiNote S…...
pod内部共享命名空间与k8s命名空间是一个东西吗?
文章目录 小知识-命名空间**下面着重介绍一下刚刚提到的内部命名空间**IPC NamespaceNetwork Namespace 本文摘自于我的免费专栏《Kubernetes从0到1(持续更新)》请多关注 小知识-命名空间 注意,首先我要强调一点,Kubernetes命名空…...
Linux笔记---进程间通信:匿名管道
1. 管道通信 1.1 管道的概念与分类 管道(Pipe) 是进程间通信(IPC)的一种基础机制,主要用于在具有亲缘关系的进程(如父子进程、兄弟进程)之间传递数据,其核心特性是通过内核缓冲区实…...
JAVA设计模式——(三)桥接模式
JAVA设计模式——(三)桥接模式(Bridge Pattern) 介绍理解实现武器抽象类武器实现类涂装颜色的行为接口具体颜色的行为实现让行为影响武器修改武器抽象类修改实现类 测试 适用性 介绍 将抽象和实现解耦,使两者可以独立…...
设计模式--工厂模式详解
工厂模式 作用: 实现了创建者与调用者的分离 详细分类 简单工厂模式 工厂方法模式 抽象工厂模式 OOP七大原则: 开闭原则:一个软件的实体应该对拓展开发,对修改关闭 依赖反转原则:要针对接口编程,不…...
每天五分钟深度学习PyTorch:图像的处理的上采样和下采样
本文重点 在pytorch中封装了上采样和下采样的方法,我们可以使用封装好的方法可以很方便的完成采样任务,采样分为上采样和下采样。 上采样和下采样 下采样(缩小图像)的主要目的有两个:1、使得图像符合显示区域的大小;2、生成对应图像的缩略图。 下采样( 放大图像)的…...
前端面试场景题
目录 1.项目第一次加载太慢优化 / vue 首屏加载过慢如何优化 2.说说了解的es6-es10的东西有哪些 ES6(ES2015)之后,JavaScript 新增了许多实用的数组和对象方法,下面为你详细介绍: 3.常见前端安全性问题 XSS&#…...
国际化不生效
经过我的重重检查 最终发现是 版本问题。 原本下载默认next版本cnpm install vue-i18nnext 下载 国际化插件 cnpm install vue-i18n^9.14.3 删除掉node_models,再重新加载包:cnpm install 这时候就可以正常显示了 国际化操作: en.js zh…...
新一代人工智能驱动医疗数智化:范式变革、实践方向及路径选择
人工智能(AI)正以前所未有的速度重构医疗健康行业的底层逻辑,从数据获取、知识建模到临床决策支持,AI不仅是“辅助工具”,更日益成为医疗生产力体系的核心引擎。随着大模型、计算平台和数智基础设施的迅猛发展,医疗数智化正进入从“点状创新”走向“系统重构”的深水区。…...
OpenCV 图形API(55)颜色空间转换-----将图像从 RGB 色彩空间转换为 I420 格式函数RGB2I420()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 将图像从 RGB 色彩空间转换为 I420 色彩空间。 该函数将输入图像从 RGB 色彩空间转换为 I420。R、G 和 B 通道值的常规范围是 0 到 255。 输出图…...
大模型安全吗?数据泄露与AI伦理的黑暗面!
大模型安全吗?数据泄露与AI伦理的黑暗面! 随着人工智能技术的飞速发展,尤其是大型语言模型(如GPT-3、BERT等)的出现,AI的应用场景越来越广泛,从智能客服到内容生成,从医疗诊断到金融…...