AutoMQ 如何实现没有写性能劣化的极致冷读效率
前言
追赶读(Catch-up Read,冷读)是消息和流系统常见和重要的场景。
-
削峰填谷:对于消息来说,消息通常用作业务间的解耦和削峰填谷。削峰填谷要求消息队列能将上游发送的数据堆积住,让下游在容量范围内消费,这时候下游追赶读的数据都是不在内存中的冷数据。
-
批处理场景:对于流来说,周期性的批处理任务需要从几个小时甚至一天前的数据开始扫描计算。
-
故障恢复:消费者宕机故障若干小时后恢复重新上线;消费者逻辑问题,修复后,回溯消费历史数据。
追赶读主要关注两点:
-
追赶读的速度:追赶读速度越快。业务就能更快从故障中恢复,降低故障影响时间。批处理任务就能更快产出分析结果,产出报表和决策。
-
读写的隔离性:追赶读需要尽量不影响消息发送的速率和延时。
Apache Kafka 一直以来都以极致的吞吐能力受到广大开发者和使用者的喜爱。AutoMQ[1] 在保证与 Apache Kafka 100% 兼容并且提供极致弹性和降本能力的基础上,不仅做到了相比Kafka更加极致的吞吐能力,同时还解决了Kafka冷读时,写吞吐性能劣化的问题。接下来,本文将从追赶读的实现来说明 AutoMQ 如何做到单机 1K 分区并发追尾读达到 1GB/s 的极致吞吐能力,并且在追赶读过程中避免发送流量的性能劣化。
追赶读实现
架构概览
AutoMQ 针对流顺序连续读取的特征参考 Linux 的 PageCache 设计了 BlockCache 层。BlockCache 会对上层屏蔽与对象存储交互的细节,上层只需要发起指定位点的读取请求,BlockCache 会进行读取请求合并、数据预读、数据缓存和缓存驱逐,以达到最佳的追赶读吞吐、缓存利用率和 API 调用成本。
那为什么叫 BlockCache 不叫 PageCache 或者 RecordCache?
要回答这个问题,首先需要介绍 AutoMQ 在对象存储上一个对象的存储格式,一个对象由三大部分组成:
-
Data Block:存储一个 Stream 连续的 Records 数据段,一个对象中可以有多个不同 Stream 的 Data Block。
-
Index Block:存储 Data Block 的索引信息
{streamId, startOffset, endOffset, recordCount, blockPosition, blockSize}
,每次从对象中读取数据,首先是需要从 Index Block 二分查找定位到对应的 Data Block 索引,然后再去执行真正的数据块读取。 -
Footer:存储格式版本和 Index Block 位置等信息。
<beginning>
[data block 1]
[data block 2]
...
[data block N]
[index block]
[Footer]
<end>
AutoMQ 从对象存储读取和缓存都是以 Data Block 为最小维度,因此追赶读的缓存称作 BlockCache。
BlockCache 架构如下图,主要由 4 部分组成:
-
KRaft Metadata:存储 Stream 的 Offset 段到对象的关系。
-
StreamReader:读取窗口,每个消费者消费每个分区都会有自己独立的读取窗口。窗口内主要维护还未完成读取的 Data Block 的索引信息,并且在适当的时候触发预读加速。
-
DataBlockCache:Data Block 数据缓存,通过堆外内存缓存从对象存储读取的数据块,采用关注度和 LRU(Least Recently Used)机制来进行缓存管理。
-
ObjectStorage:对象存储的 API 抽象层,抹平不同云对象存储的差异,并提供读取合并加速。
BlockCache 发起一次追赶读,各个组件的交互流程简单描述如下:
-
首先根据读取的
{streamId, startOffset}
定位到 StreamReader; -
然后 StreamReader 会向 KRaft Metadata 请求 {startOffset, endOffset} 下负责的对象的元信息;
-
StreamReader 根据对象元信息读取对象的 IndexBlock,并二分查找出对应的 DataBlock 索引(若内存中已经有索引信息则跳过步骤2 / 3);
-
StreamReader 向 DataBlockCache 请求 DataBlock;
-
DataBlockCache 向 ObjectStorage 发送对象的
#rangeRead
请求(若已经缓存则直接返回); -
ObjectStorage 读取对应的数据段返回给上层。
基础概念和流程介绍完成,再来剖析一下 “AutoMQ 如何做到单机 1K 分区并发追尾读达到 1GB/s”。
1K 分区并发追尾读
AutoMQ 实现单机 1K 分区并发追尾读的关键是控制每个 Stream 读取的缓存空间占用。避免总缓存诉求超过缓存空间上限,不同 Stream 的缓存互相驱逐导致从对象存储读取的网络带宽和 API 成本浪费。
AutoMQ 可以将每个 Stream 的读取缓存空间占用控制在 2MB 以下,意味着只需要 2GB 的 BlockCache 就能支撑 1K 分区的并发追尾读。
前面提到 BlockCache 的最小缓存粒度是对象的 DataBlock。DataBlock 默认大小为 512KB(软限制),因此 Stream 读取缓存空间占用为 512KB * N(缓存的 DataBlock 个数)。那么减少空间占用的目标,就是去尽可能减少 N 的值,而 N 值的大小主要由缓存驱逐策略决定。
在通用的缓存中通常采用 Least Recently Used 来作为缓存驱逐策略,但实测下来这种策略对顺序读取的流场景并不是特别适配,仍旧会出现较多的误驱逐问题。举个例子,假设有 2 个分区在并发追尾读,2 个分区的读取速率分别是 10MB/s 和 1MB/s,1MB/s 分区的 DataBlock 访问和更新频率比 10MB/s 分区低,那么很有可能由于 LRU,1MB/s 分区缓存的 DataBlock 还未被读完,就被 10MB/s 分区新加载的 DataBlock 所驱除。
为了解决这个问题,AutoMQ 在 LRU 的基础上新增基于关注度(Watch)驱逐策略。读取窗口(StreamReader)内正在读取或者将来准备要读取的 DataBlock,读取窗口会给该 DataBlock 标记关注度 + 1,当读取窗口将这个 DataBlock 读取完成后会释放 DataBlock 的关注度 -1。BlockCache 会优先采用基于关注度的驱逐策略,当 DataBlock 的关注度减为 0 时,即使 BlockCache 还有缓存空间,该 DataBlock 的缓存也会被立即驱逐。
通过关注度驱逐策略,在不考虑预读的场景,Stream 的每个读取窗口至多占用 512KB * 3 = 1.5MB(Kafka 的默认 max.partition.fetch.bytes
为 1MB,读取的位点如果在 DataBlock 中间,则至多读取 3 个 DataBlock)。同样在 2 分区 10MB/s 和 1MB/s 并发读取的场景,AutoMQ 的追尾读缓存占用会稳定在 4MB,并且 2 个读取窗口会互相隔离,不会出现缓存互相驱逐的情况。
1GB/s 读取吞吐
追赶读的分区并发能力决定了 Kafka 能支撑多少业务同时追赶读。读取吞吐决定了业务决策的效率。AutoMQ 提供单机 1GB/s 追赶读吞吐主要由两点决定:对象存储和预读。
对象存储,虽然对象存储的操作耗时通常是百毫秒级别的,但是只要使用侧只提供充足的并发,即使不添加任何读写的优化,在对象存储后端庞大的资源池下,可以轻松提供 GB/s 的读写吞吐。以 S3 举例,假设 4MB 读取需要花费 100ms,那么只需要 25 个并发就可以达到 1 GB/s 的读取速度。
预读,Kafka 的追赶读消费宏观上看读取数据 -> 处理数据 -> 读取数据的循环,如果是直接透传请求到对象存储,那么对象存储的高延迟,会让读取的并发无法被充分利用,最终导致读取吞吐不理想。因此 AutoMQ 通过缓存预读来减少追赶读 Fetch 请求的处理耗时,尽量使得后续的追赶读请求均可被预读窗口所覆盖,以提高读取吞吐。
细心的读者这时候会有疑问了:AutoMQ 的缓存预读策略会不会导致 Stream 读取窗口占用过大,以至于出现 10MB 和 1MB 并发读取的互相驱逐现象么?
AutoMQ 为了避免这种情况的出现采取了以下预读策略:
-
预读大小初始为 512KB,只有在读取窗口内上层读取出现 Cache Miss 时才会触发预读窗口大小的增加。未出现 Cache Miss,则说明当前预读的速度能满足追赶读的需求。
-
读取窗口中的预读窗口最大不会超过 32MB。
-
只有在 BlockCache 还有空余空间的时候才会发起预读,避免了内存紧张的情况下仍旧发起预读导致误驱逐。
读写隔离
AutoMQ 在支持追尾读高并发和高吞吐的同时,通过读写隔离确保了发送流量不受影响。如下图所示,AutoMQ 的读写隔离主要由两部分保障:
-
读写链路隔离:写入链路,Producer 发送的消息存储到 EBS WAL 后就会响应给客户端成功;追赶读链路,追赶读的数据来自于 S3,因此也不会争抢 EBS WAL 的磁盘带宽和 IOPS。
-
网络优先级限流:AutoMQ 可以设置整体的网络流入流出限制,并且 Producer 流量优先级高于追赶读 Consumer 的流量优先级,因此不会出现追赶读流量占满网络带宽从而影响发送的情况。
压测
环境准备
-
服务端:阿里云 ecs.g8i.4xlarge,16C64G,数据盘 PL1 300GB
-
压力机:阿里云 ecs.g8i.4xlarge,16C64G
AutoMQ 启动命令:堆内 32G,堆外 24G,BlockCache 14G,带宽限制 2GB/s。
# AutoMQ Version >= 1.2
KAFKA_S3_ACCESS_KEY=xxxx KAFKA_S3_SECRET_KEY=xxxx KAFKA_HEAP_OPTS="-Xmx32g -Xms32g -XX:MaxDirectMemorySize=24G" ./bin/kafka-server-start.sh -daemon config/kraft/server.properties \
--override node.id=0 \
--override cluster.id=M_automq-catchup_____w \
--override controller.quorum.voters=0@${ip}:9093 \
--override advertised.listener=${ip}:9092 \
--override s3.data.buckets='0@s3://xxx_bucket?region=oss-cn-hangzhou&endpoint=https://oss-cn-hangzhou-internal.aliyuncs.com' \
--override s3.wal.path='0@file:///dev/nvme1n1?capacity=21474836480&iodepth=32&iops=4000' \
--override s3.telemetry.metrics.exporter.uri='otlp://?endpoint=http://xxxx&protocol=grpc' \
--override s3.stream.allocator.policy=POOLED_DIRECT \
--override s3.wal.cache.size=6442450944 \
--override s3.wal.upload.threshold=1572864000 \
--override s3.block.cache.size=12884901888 \
--override s3.network.baseline.bandwidth=2147483648 \
--override s3.stream.object.split.size=1048576
压测脚本:创建 50 个 Topic,每个 Topic 20 个分区,总共 1000 个分区,以 200MB/s 持续写入2 小时,然后从头开始消费,并且消费过程中仍旧保持 200MB/s 的写入流量。
KAFKA_HEAP_OPTS="-Xmx32g -Xms32g" nohup ./bin/automq-perf-test.sh --bootstrap-server ${bootstrapServer}:9092 \
--producer-configs batch.size=0 \
--consumer-configs fetch.max.wait.ms=1000 \
--topics 50 \
--partitions-per-topic 20 \
--producers-per-topic 2 \
--groups-per-topic 1 \
--consumers-per-group 4 \
--record-size 65536 \
--send-rate 3200 \
--backlog-duration 7200 \
--group-start-delay 0 \
--warmup-duration 1 \
--reset &
压测结果
-
1000 个分区 2 个小时总共生产 1.37 TB 的数据;
-
追赶读消费峰值 1.6GB/s,每个 Topic 均保持 32MB/s 的消费速度,总共耗时 18 分钟消费完 1.37 TB 的积压数据;
-
追赶读期间发送流量仍旧稳定在 200MB/s,发送耗时 P99 从 5ms 上涨到 10ms,平均耗时仍旧维持在 2ms 以下;
参考资料
[1] AutoMQ: https://www.automq.com
[2] AutoMQ vs. Apache Kafka Benchmark: https://docs.automq.com/automq/benchmarks/benchmark-automq-vs-apache-kafka#catch-up-read
相关文章:
AutoMQ 如何实现没有写性能劣化的极致冷读效率
前言 追赶读(Catch-up Read,冷读)是消息和流系统常见和重要的场景。 削峰填谷:对于消息来说,消息通常用作业务间的解耦和削峰填谷。削峰填谷要求消息队列能将上游发送的数据堆积住,让下游在容量范围内消费…...
启动gateway时Failed to configure a DataSource
问题 在启动网关时候启动失败,报错: 原因很明显,就是没有配制数据库连接信息 实际上是因为在网关模块中导入的某个依赖里面引入了MyBatis的依赖,导致启动的时候自动配置数据库源 但是在这个网关模块中是不需要数据数据库的 解决...
node 程序占用处理方法与后台运行方法
程序占用 如果你在关闭终端后重新运行 node server.js,但提示端口 3000 被占用,说明之前的服务器进程仍然在后台运行。以下是解决方法: 1. 检查后台运行的 Node.js 进程 首先,检查是否有 Node.js 进程正在占用端口 3000。 在 L…...
C# OpenCV机器视觉:对位贴合
在热闹非凡的手机维修街上,阿强开了一家小小的手机贴膜店。每天看着顾客们自己贴膜贴得歪歪扭扭,不是膜的边缘贴不整齐,就是里面充满了气泡,阿强心里就想:“要是我能有个自动贴膜的神器,那该多好啊…...
【计算机网络】TCP/IP 网络模型有哪几层?
目录 应用层 传输层 网络层 网络接口层 总结 为什么要有 TCP/IP 网络模型? 对于同一台设备上的进程间通信,有很多种方式,比如有管道、消息队列、共享内存、信号等方式,而对于不同设备上的进程间通信,就需要网络通…...
本地部署Deepseek R1
使用Ollama open-webui部署Deepseek R1 一、安装Ollama 官网地址:https://ollama.com/,点击下载按钮选择windows版本。并安装 打开命令提示符输入ollama,出现一下提示命令表示ollama安装完成 二、使用Ollama下载deepseek R1不同模型 打开o…...
PHP盲盒商城系统源码 晒图+免签+短信验证+在线回收 thinkphp框架
源码介绍 PHP盲盒商城系统源码 晒图免签短信验证在线回收 thinkphp框架 源码前端uniapp开发,可以打包成APP(非H5封壳)H5,接其他平台支付通道,前后端全开源 H5盲盒首页可以直接开盒新UI 修复优化BUG,修复无…...
[Do374]ansible-nagivator考前整理
[Do374]ansible-nagivator考前整理 1. Ansible-Navigator 升级后的变化1.1 主要变化1.2 重大改变 2. ansible主要配置文件2.1 .ansible-navigator.yml2.2 ansible.cnf 3. 常用模块3.1 file模块3.2 copy模块3.3 user模块和lookup模块3.4 yum和yum_repository模块3.5 systemd和se…...
deepseek+kimi自动生成ppt
打开deepseek官网,输入详细的需求,让他生成个ppt 接着deepseek开始思考生成了 接着复制生成了的内容 打开kimi粘贴刚才deepseek生成的内容 可以一键生成啦,下载编辑使用吧...
循环神经网络学习01——transformer:输入部分-嵌入层位置编码
一、介绍 1、核心思想 利用自注意力机制来捕获输入序列中各元素之间的全局依赖关系,无论这些元素之间的实际距离有多远。 自注意力机制:允许模型在处理序列的每个元素时,考虑到序列中的所有其他元素,从而捕捉它们之间的关系和依…...
centos系统清理docker日志文件
在CentOS系统中,Docker日志文件的不断增长可能会占用大量磁盘空间,影响系统性能和正常运行。为了保持系统的健康状态,需要定期清理Docker日志文件。本文将详细介绍如何在CentOS系统上清理Docker日志文件的具体步骤和方法。 Docker日志文件位…...
低成本+高性能+超灵活!Deepseek 671B+Milvus重新定义知识库搭建
“老板说,这个项目得上Deepseek,还得再做个知识库...” 还有哪个开发者,最近没听到这样的抱怨? Deepseek爆火,推理端的智能提速,算力成本急剧下降,让不少原本不想用大模型,用不起大模型的企业&a…...
Windows 本地部署大模型 OpenWebUI+Ollama
安装Ollama Ollama官方网址:https://ollama.com 下载运行大模型 在Ollama官网中查看需要下载的大模型 https://ollama.com/library 复制图片中的链接 打开cmd,运行此命令(此过程会时间会很久) 下载Miniconda Miniconda作用是…...
【iOS自动化】Xcode配置WebDriverAgent
WebDriverAgent 是 iOS 端自动化测试的工具,这里记录下 MacOS 环境 Xcode 如何配置 WebDriverAgent。 【重要】环境准备 ‼️ 注意:Xcode 版本需要支持对应的 iOS 版本,而 Xcode 版本又依赖 MacOS 版本;在开始部署前,…...
RabbitMQ 延迟队列
1.延迟队列插件安装(版本号要对其) Releases rabbitmq/rabbitmq-delayed-message-exchange GitHub 下载的文件: rabbitmq_delayed_message_exchange-3.13.0.ez 直接复制到以下文件夹: \RabbitMQ Server\rabbitmq_server-3.13.7\plugins\ 执行命令…...
JVM-Java虚拟机
基础知识 JVM的定义与作用 定义:JVM是Java语言的一部分,它是一个虚拟的计算机,通过它可以执行Java程序。 作用: 跨平台支持:实现了“编译一次,到处运行”的目标。 自动内存管理:通过垃圾回收…...
Unity底层C#处理机制深度解析
一、Unity脚本执行架构 Unity采用分层架构处理C#脚本,核心由以下组件构成: 脚本引擎层 Mono Runtime(旧版本) IL2CPP(2015版本) Burst Compiler(DOTS体系) 原生交互层 Runtime …...
【WB 深度学习实验管理】使用 PyTorch Lightning 实现高效的图像分类实验跟踪
本文使用到的 Jupyter Notebook 可在GitHub仓库002文件夹找到,别忘了给仓库点个小心心~~~ https://github.com/LFF8888/FF-Studio-Resources 在机器学习项目中,实验跟踪和结果可视化是至关重要的环节。无论是调整超参数、优化模型架构,还是监…...
MFC 应用最小化到系统托盘
本指南将实现 MFC 应用程序在关闭时最小化系统托盘的功能,并左键和右键系统托盘图标进行交互。 目标: 左键点击托盘图标:恢复对话框窗口。右键点击托盘图标:弹出右键菜单,提供 恢复窗口 和 退出程序 两个选项。退出时…...
C++ ——从C到C++
1、C的学习方法 (1)C知识点概念内容比较多,需要反复复习 (2)偏理论,有的内容不理解,可以先背下来,后续可能会理解更深 (3)学好编程要多练习,简…...
【OCPP】ocpp1.6J协议框架说明
目录 1.简介 1.1.本文件的目的 1.2.目标受众 1.3. OCPP-S and OCPP-J 1.4. 约定 1.5.定义和缩写 1.6.参考 2.优点和问题 3.连接 3.1.客户要求 3.1.1.连接URL 3.1.2.OCPP版本 3.1.3.打开HTTP请求的示例 3.2.服务器响应 3.3.更多信息 4.RPC框架 4.1.介绍 4.1.1…...
Swipe横滑与SwipeItem自定义横滑相互影响
背景 vue项目,H5页面,使用vant的组件库轮播组件<Swipe>,UI交互要求,在每个SwipeItem中有内容,可自横滑,查看列表内容 核心代码 <template><Swipeclass"my_swipe":autoplay&quo…...
渗透利器工具:Burp Suite 联动 XRAY 图形化工具.(主动扫描+被动扫描)
Burp Suite 联动 XRAY 图形化工具.(主动扫描被动扫描) Burp Suite 和 Xray 联合使用,能够将 Burp 的强大流量拦截与修改功能,与 Xray 的高效漏洞检测能力相结合,实现更全面、高效的网络安全测试,同时提升漏…...
C# 学习目录
以下内容仅供参考 基础概念 数据类型(使用与定义)-CSDN博客 var使用-CSDN博客 运算符(new、sizeof、is、as)_new 运算符-CSDN博客 数据结构 数组定义与使用-CSDN博客 动态数组和泛型集合-CSDN博客 字典(Dictonary)-CSDN博客 集合类型࿰…...
react native学习【9】——动态路由
react native学习【9】——动态路由 1、进入终端2、动态路由dynamic router3、编写app/_layout.jsx布局文件4、创建动态路由5、完善index.jsx文件6、完善[id].jsx文件扩展运算符...7、完整的index.jsx文件1、进入终端 2、动态路由dynamic router 官方网站 视频中的举例:当我们…...
[AI]Mac本地部署Deepseek R1模型 — — 保姆级教程
[AI]Mac本地部署DeepSeek R1模型 — — 保姆级教程 DeepSeek R1是中国AI初创公司深度求索(DeepSeek)推出大模型DeepSeek-R1。 作为一款开源模型,R1在数学、代码、自然语言推理等任务上的性能能够比肩OpenAI o1模型正式版,并采用MI…...
LeetCodehot 力扣热题100 验证二叉搜索树
class Solution {vector<int> nums; // 用来存储二叉树节点值的数组 public:bool isValidBST(TreeNode* root) {inorder(root); // 中序遍历二叉树,填充 nums 数组// 遍历 nums 数组,检查是否为严格递增序列for(int i0; i<nums.size()-1; i){…...
使用Kickstart配置文件封装操作系统实现Linux的自动化安装
使用Kickstart配置文件封装操作系统实现Linux的自动化安装 创建ks.cfg配置文件 可以使用已经安装完成的Linux操作系统中的/root目录下的anaconda.cfg配置文件 注意,配置文件会因为kickstart的版本兼容性的问题导致无法安装报错需要在实际使用过程中删除某些参数 …...
前端开发架构师Prompt指令的最佳实践
前端开发架构师Prompt 提示词可作为系统提示词使用,可基于用户的需求输出对应的编码方案。 本次提示词偏向前端开发的使用,如有需要可适当修改关键词和示例。 推荐使用 Cursor 中作为自定义指令使用Cline 插件中作为自定义指令使用在力所能及的范围内使…...
flink判断两个事件之间有没有超时(不使用CEP)
1.为啥不使用cep呢,cep的超时时间设置不好配置化,无法满足扩展要求 2.超时怎么界定。A事件发生后,过了N时间,还没有收到B事件,算超时。 代码如下: import com.alibaba.fastjson.JSONObject; import lombo…...
vue3+ts+vite+element plus设置日期时间禁止选择小于当前时间精确到时分秒
ts组件 // timeUtils.ts/*** 生成一个数组* param start* param end*/ export const makeRange (start: number, end: number): number[] > {const result: number[] [];for (let i start; i < end; i) {result.push(i);}return result; };/*** 限制今天之前的时间不…...
2025web寒假作业二
一、整体功能概述 该代码构建了一个简单的后台管理系统界面,主要包含左侧导航栏和右侧内容区域。左侧导航栏有 logo、管理员头像、导航菜单和安全退出按钮;右侧内容区域包括页头、用户信息管理内容(含搜索框和用户数据表格)以及页…...
2025.2.8——二、Confusion1 SSTI模板注入|Jinja2模板
题目来源:攻防世界 Confusion1 目录 一、打开靶机,整理信息 二、解题思路 step 1:查看网页源码信息 step 2:模板注入 step 3:构造payload,验证漏洞 step 4:已确认为SSTI漏洞中的Jinjia2…...
Mysql 函数解析
文章目录 一、模糊匹配【like】二、CASE函数1、简单case2、搜索case3、搜索case 聚合函数 一、模糊匹配【like】 一般形式为:列名 [NOT] LIKE ‘%关键字%’,示例如下: like %北京%列名包括北京的字样like ‘北京%’ 列名北京开头like ‘%北…...
Docker 部署 MongoDB | 国内阿里镜像
一、简易单机版 1、镜像拉取 docker pull registry.cn-hangzhou.aliyuncs.com/farerboy/mongo:8.0.5-rc1 2、运行镜像 docker run -it --name mongodb \ -e MONGO_INITDB_ROOT_USERNAMEmongoroot \ -e MONGO_INITDB_ROOT_PASSWORDmongoroot \ -v /wwwroot/opt/docker/mong…...
加速度计信号处理
【使用 DSP 滤波器加速速度和位移】使用信号处理算法过滤加速度数据并将其转换为速度和位移研究(Matlab代码实现)_加速度计滤波器-CSDN博客 https://wenku.baidu.com/view/622d38b90f22590102020740be1e650e52eacff9.html?_wkts_1738906719916&bdQ…...
Baumer工业相机堡盟相机的相机传感器芯片清洁指南
Baumer工业相机堡盟相机的相机传感器芯片清洁指南 Baumer工业相机1.Baumer工业相机传感器芯片清洁工具和清洁剂2.Baumer工业相机传感器芯片清洁步骤2.1、准备步骤2.2、清洁过程1.定位清洁工具2.清洁传感器3.使用吹风装置 Baumer工业相机传感器芯片清洁的优势设计与结…...
20240824 美团 笔试
文章目录 1、单选题1.11.21.31.41.51.61.71.81.91.101.111.121.131.141.151.161.171.181.191.202、编程题2.12.2岗位:硬件开发工程师(嵌入式系统软件开发方向) 题型:20 道单选题,2 道编程题题 1、单选题 1.1 C 语言中,如果输入整数 v 是 2 的幂,下面表达式中哪个会返…...
【扫描件PDF】如何批量识别扫描件PDF多个区域内容保存到Excel表格,基于WPF和腾讯OCR的详细解决方案
在很多实际业务场景中,需要对大量扫描件 PDF 中的特定区域内容进行识别并整理到 Excel 表格里,以下是一些常见的应用场景:物流运单扫描件 PDF 中包含发货人信息、收货人信息、货物信息等。批量识别这些区域内容到 Excel 表格,有助…...
Django开发入门 – 3.用Django创建一个Web项目
Django开发入门 – 3.用Django创建一个Web项目 Build A Web Based Project With Django By JacksonML 本文简要介绍如何利用最新版Python 3.13.2来搭建Django环境,以及创建第一个Django Web应用项目,并能够运行Django Web服务器。 创建该Django项目需…...
C# OpenCV机器视觉:OSTU算法实现背景差分的自适应分割
在一个热闹的科技公司里,阿强是一个负责图像分析的员工。他的日常工作就是从各种复杂的图像中提取出有用的信息,可这可不是一件轻松的事情哦 最近,阿强接到了一个艰巨的任务:要从一堆嘈杂的监控图像中分离出运动的物体,…...
SIPp的参数及命令示例
以下是SIPp参数的分类表格整理,方便快速查阅和使用: SIPp 参数分类表格 分类参数描述默认值示例基本参数-sc指定XML场景文件(客户端模式)无-sc uac.xml-sd指定XML场景文件(服务器端模式)无-sd uas.xml-i本…...
【Mac排错】ls: command not found 终端命令失效的解决办法
【TroubleShooting on Mac】ls: command not found 终端命令失效的解决办法 A Solution to Solve “Command not found” of Terminal on Mac 一直在使用心爱的MacBook Pro的Terminal,并且为她定制了不同的Profile。 这样,看起来她可以在不同季节&…...
【OneAPI】通过网页预渲染让搜索引擎收录网页
API简介 网页预渲染,适用于动态网页以及单页面的SEO,支持网页缓存。 您无须更改代码即可让搜索引擎收录您的网页。只要将需要预渲染的页面转发的本接口即可。 如果您使用Nginx作为网页服务器,推荐使用以下配置: #您的网站locat…...
51单片机(国信长天)矩阵键盘的基本操作
在CT107D单片机综合训练平台上,首先将J5处的跳帽接到1~2引脚,使按键S4~S19按键组成4X4的矩阵键盘。在扫描按键的过程中,发现有按键触发信号后(不做去抖动),待按键松开后,在数码管的第一位显示相应的数字:从左至右&…...
git命令行删除远程分支、删除远程提交日志
目录 1、从本地通过命令行删除远程git分支2、删除已 commit 并 push 的记录 1、从本地通过命令行删除远程git分支 git push origin --delete feature/feature_xxx 删除远程分支 feature/feature_xxx 2、删除已 commit 并 push 的记录 git reset --hard 7b5d01xxxxxxxxxx 恢复到…...
05-多数元素
给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 方法一:哈希表法 通过哈希表来记录每个元素出现的次数,…...
一个简单的Windows TCP服务器实现
初始化 WSADATA wsaData; SOCKET serverSocket, clientSocket; struct sockaddr_in serverAddr { 0x00 }; struct sockaddr_in clientAddr { 0x00 }; int clientAddrLen sizeof(clientAddr);if (WSAStartup(MAKEWORD(2, 2), &wsaData) ! 0) {printf("WSAStartup f…...
salesforce 中 Account 转移给新 Owner 后如何仅转移 Case,而不转移 Opportunity
在 Salesforce 中,当更改 Account Owner 时,系统默认会将所有相关的 Opportunities(商机) 和 Cases(案例) 也一并转移给新的 Account Owner。如果你希望 仅转移 Case,而不转移 Opportunities&am…...
Spring Boot 中的日志配置
文章目录 Spring Boot 中日志配置的源码分析1. Spring Boot 日志框架的选择与自动配置2. 日志自动配置与默认行为3. 日志系统的核心组件:Logger 和 LoggerFactory4. 日志配置文件的解析配置日志级别配置日志输出格式和目标 5. 日志级别的控制自定义日志级别 6. 自定…...