TiDB 扩容过程中 PD 生成调度的原理及常见问题丨TiDB 扩缩容指南(一)
导读
作为一个分布式数据库,扩缩容是 TiDB 集群最常见的运维操作之一。本系列文章,我们将基于 v7.5.0 具体介绍扩缩容操作的具体原理、相关配置及常见问题的排查。
通常,我们根据当前资源状态来决定是否需要调整 TiKV 节点的规模,无论是增加还是减少节点。我们希望在调整后,集群能够通过重新调度尽快实现所有在线 TiKV 节点资源的平衡利用。
因此对于扩缩容来说,我们主要关心的还是以下两点:
- 资源均衡调度指令产生速度(PD 上调度产生的速度 )
- 资源均衡调度指令执行速度(TiKV 间数据搬迁的速度)
本系列文章将围绕以上两个逻辑,重点介绍扩缩容过程中的核心模块及常见问题,分为以下几个部分:
- 扩缩容调度生成原理及常见问题:
- 扩容过程中调度生成原理及常见问题
- 缩容过程中调度生成原理及常见问题
- 扩缩容过程调度执行(TiKV 副本搬迁)的原理及常见问题
本文我们将重点介绍 TiDB 扩容过程中 PD 生成调度的原理和常见问题,希望能够帮助大家更好地理解和运维 TiDB。
扩容过程中 PD 生成调度的原理及常见问题
一般的,当集群中 TiKV 资源跑到 75% 左右时,一般的调优手段无法解决资源使用上的瓶颈,此时,我们就需要通过 添加 tikv 节点的方式,来提高集群的整体性能。
如图,当集群只有 三个 tikv 时,能够使用的存储、CPU 、 memory 到达使用瓶颈时,我们可以通过加节点的方式增加集群相关资源。下面我们简单来看一下,三 tikv 节点下,增加一个 tikv 节点时,TiDB 集群是如何让新节点的物理资源能够被集群使用起来的。首先在三个 TiKV 节点的集群中,在我们 PD 的统一调度下,会尽量将三个 tikv 节点的资源得到均衡使用。
新加入一个节点时,PD 会慢慢的将相关数据以 Region 为单位迁移到新节点上,以充分使用新节点的 存储、memory 和 CPU 等资源。这当中最重要也是最耗时的就是将 Region 的副本数据从老节点搬迁到新节点上。如下图,PD 将 Region 1 的其中一个副本从 store-3 搬迁到了新节点 store-4 上,这个过程我们叫 balance-region.
Balance region 具体步骤
Balance region 以 region 为单位执行,由 PD 计算需要搬迁的 region, 由 TiKV 执行。具体执行过程,简单的来说,主要分为以下三个步骤:
- 新节点上新增副本 learner 节点(leaner 节点不参与投票过程)。
- 将新节点的 learner 角色和老节点的 follower 角色互换
- 将老节点上的副本(learner) 删除以上步骤最终会变成一条条调度指令,下发给 KV 去执行,下面我们来看每个调度指令是如何从进行的:
Step1: Add learner
- PD 中 balance-region-scheduler 生成balance-region operator, 制定具体执行步骤。
- PD 通过心跳的方式,告诉 leader 节点执行 add learner peer 操作
- Leader 所在节点在这个 Region 的 raft-group 里面广播这个消息,并最终从 leader 上生成 snapshot 发送给 store-4 , 添加 learner 节点完成。
- Leader 收到来自 learner 的消息,上报心跳给 PD 告知 add learner 这一步骤执行成功
Step2: Switch role
store-4 上的 learner 节点虽然有完整的数据,但不参与投票过程。我们期望是将 store-3 上的 follower 迁移到 store-4 上,因此,在这一步骤,我们会将 store-4 和 store-3 上的副本的角色互换,最终 store-3 上的老副本会变成 learner, 而新节点上的副本角色变成 voter 也就是 follower.这个过程为了保证数据的安全性,实际情况分为两条调度指令执行。
具体执行步骤为:
- PD 通过心跳知道 learner 添加成功后,发送角色互换的指导给 leader 节点
- Leader 节点在 raft-group 里面广播消息
- 所有副本收到该心跳后,更新自己的配置。至此,该 raft-group 完成角色互换的配置更新。
这个过程因为只涉及逻辑变更,很快,也很难出问题。
Step3: Remove old peer
经过步骤 2,store-4 上已经有一个 follower, 且已经不会有数据访问到 store-3 上的 learner, 因此我们可以安全的删除这个副本。具体执行步骤如下:
- PD 发送心跳给 leader, 告知删除 store-3 上的副本
- Leader 在当前 region 的 raft-group 里面广播这个消息
- 所有副本在收到这个消息后,更新自己的配置信息,而 store-3 则会将自己这个副本完全删除。
PD 上关键日志
以上过程,我们可以从 PD 的日志中看到完整的执行情况:
create balance-region operator
// create balance-region operator
[2024/07/09 16:25:23.105 +08:00] [INFO] [operator_controller.go:488] ["add operator"] [region-id=142725] [operator="\"balance-region {mv peer: store [1] to [166543141]} (kind:region, region:142725(575, 5), createAt:2024-07-09 16:25:23.105733052 +0800 CST m=+1209042.707881308, startAt:0001-01-01 00:00:00 +0000 UTC, currentStep:0, size:92, steps:[0:{add learner peer 166543143 on store 166543141}, 1:{use joint consensus, promote learner peer 166543143 on store 166543141 to voter, demote voter peer 142726 on store 1 to learner}, 2:{leave joint state, promote learner peer 166543143 on store 166543141 to voter, demote voter peer 142726 on store 1 to learner}, 3:{remove peer on store 1}], timeout:[17m0s])\""] [additional-info="{\"sourceScore\":\"817938.92\",\"targetScore\":\"4194.83\"}"]
Step1: add learner peer on new store
// Step1: add learner node
[2024/07/09 16:25:23.105 +08:00] [INFO] [operator_controller.go:732] ["send schedule command"] [region-id=142725] [step="add learner peer 166543143 on store 166543141"] [source=create]
[2024/07/09 16:25:23.107 +08:00] [INFO] [region.go:751] ["region ConfVer changed"] [region-id=142725] [detail="Add peer:{id:166543143 store_id:166543141 role:Learner }"] [old-confver=5] [new-confver=6]
[2024/07/09 16:25:23.108 +08:00] [INFO] [operator_controller.go:732] ["send schedule command"] [region-id=142725] [step="add learner peer 166543143 on store 166543141"] [source=heartbeat
Step2/Step3: use joint consensus to switch role
// Step2: use joint consensus
[2024/07/09 16:25:24.248 +08:00] [INFO] [operator_controller.go:732] ["send schedule command"] [region-id=142725] [step="use joint consensus, promote learner peer 166543143 on store 166543141 to voter, demote voter peer 142726 on store 1 to learner"] [source=heartbeat]
[2024/07/09 16:25:24.250 +08:00] [INFO] [region.go:751] ["region ConfVer changed"] [region-id=142725] [detail="Remove peer:{id:142726 store_id:1 },Remove peer:{id:166543143 store_id:166543141 role:Learner },Add peer:{id:142726 store_id:1 role:DemotingVoter },Add peer:{id:166543143 store_id:166543141 role:IncomingVoter }"] [old-confver=6] [new-confver=8]
// Step3: leave joint state
[2024/07/09 16:25:24.250 +08:00] [INFO] [operator_controller.go:732] ["send schedule command"] [region-id=142725] [step="leave joint state, promote learner peer 166543143 on store 166543141 to voter, demote voter peer 142726 on store 1 to learner"] [source=heartbeat]
[2024/07/09 16:25:24.252 +08:00] [INFO] [region.go:751] ["region ConfVer changed"] [region-id=142725] [detail="Remove peer:{id:142726 store_id:1 role:DemotingVoter },Remove peer:{id:166543143 store_id:166543141 role:IncomingVoter },Add peer:{id:142726 store_id:1 role:Learner },Add peer:{id:166543143 store_id:166543141 }"] [old-confver=8] [new-confver=10
Step4: remove old peer
// Step4: remove learner node
[2024/07/09 16:25:24.252 +08:00] [INFO] [operator_controller.go:732] ["send schedule command"] [region-id=142725] [step="remove peer on store 1"] [source=heartbeat]
[2024/07/09 16:25:24.255 +08:00] [INFO] [region.go:751] ["region ConfVer changed"] [region-id=142725] [detail="Remove peer:{id:142726 store_id:1 role:Learner }"] [old-confver=10] [new-confver=11]
PD report operator is finished
// operator finished
[2024/07/09 16:25:24.255 +08:00] [INFO] [operator_controller.go:635] ["operator finish"] [region-id=142725] [takes=1.149978179s] [operator="\"balance-region {mv peer: store [1] to [166543141]} (kind:region, region:142725(575, 5), createAt:2024-07-09 16:25:23.105733052 +0800 CST m=+1209042.707881308, startAt:2024-07-09 16:25:23.10595495 +0800 CST m=+1209042.708103209, currentStep:4, size:92, steps:[0:{add learner peer 166543143 on store 166543141}, 1:{use joint consensus, promote learner peer 166543143 on store 166543141 to voter, demote voter peer 142726 on store 1 to learner}, 2:{leave joint state, promote learner peer 166543143 on store 166543141 to voter, demote voter peer 142726 on store 1 to learner}, 3:{remove peer on store 1}], timeout:[17m0s]) finished\""] [additional-info="{\"cancel-reason\":\"\",\"sourceScore\":\"817938.92\",\"targetScore\":\"4194.83\"}"]
在具体的运维过程中,当发现上线速度缓慢时,如果有大量的 balance-region operator 执行超时,我们可以通过查看 PD 日志中具体某个 operator 的执行情况,对照着以上日志,来看 balance-region 具体卡在哪一步。
实时监控扩容速度
从上文我们知道,扩容 TiKV 的速度主要取决于数据的搬迁情况,主要分为两个因素:
- PD 产生 balance-region operator 的速度
- TiKV 消费 balance-region 的速度,也就是物理数据的搬迁速度。
在扩容后,要做到整个集群的资源的快速均匀,一般跟我们 region 的数量、size 有直接关系,当然与我们集群的繁忙程度也有关系。目前,PD 提供了一些监控可以让我们看到扩容的状态,主要有
- PD->metrics:
- Region health
- Pending-region-count: 正准备
add learner
但还没添加成功的副本 - Learner-peer-count: 当前集群中
learner
副本的个数,需要注意的是,如果集群本身有Tiflash
节点,这个数量也包含了Tiflash
节点里的learner
个数。
- Pending-region-count: 正准备
- Speed:
- Online store progress:当前扩容进度,根据剩余需要 balance 的空间计算得出
- Left time: 预估剩余时间,根据剩余需要 balance 的空间及当前数据搬迁速度得出
- Current scaling speed: 当前扩容数据搬迁实际速度
- Region health
Balance region operator 调度生成原理及常见问题
因为本身 PD 就有一系列监控和平衡各个 TiKV 之间的资源使用情况的调度器,因此 PD 没有针对扩容给出单独的调度器。目前这类调度器主要有两类:
- Balance-region-scheduler:负责将 Region 均匀的分散在集群中所有的 store 上,主要用于分散存储压力
- Balance-leader-scheduler: 负责将 region leader 均匀分布在 store 上,主要负责分散客户端的请求压力(CPU)
因此我们也可以认为,在扩容过程中,负责生成调度的主要是以上两个调度器在发挥作用。对于 balance-leader-scheduler, 因为没有数据搬迁,只是 raft-group 元数据的变更,因此特别快。一般情况下,我们不需要特别关注这个(也很少出问题) 本节将重点介绍 balance-region-scheduler, 也就是扩容情况下,迅速往新扩容 kv 上搬迁副本的调度器行为及常见问题。
首先我们来看一下 balance-region-scheduler 是如何选择并生成 balance-region operator 的:
调度原理
Balance-region-scheduler 每隔 10ms~5s/10s 会发起一次调度。balance-region-scheduler 每次生成调度的具体逻辑如下:
-
检查 region-schedule-limit ( https://docs.pingcap.com/tidb/v7.5/pd-configuration-file#region-schedule-limit ), 用于控制当前 balance-region operator 的并发数量。
-
选择本次要搬走的 store
- 空间不足时,优先选剩余空间最不足的节点 (使得 tikv 的剩余数据量均衡)
- 空间富裕时,选择已用空间最多的节点(使得 tikv 的数据量分布均衡)
- 中间状态综合考虑两个因素
- 检查 store-limit 是否符合条件:store limit remove-peer ( https://docs.pingcap.com/tidb/stable/configure-store-limit#principles-of-store-limit-v2 )
- 检查这个 store 上的 max-snapshot-count ( https://docs.pingcap.com/tidb/stable/pd-configuration-file#max-snapshot-count ) 是否超过
- 过滤选出可以作为数据源搬迁的 store, 过滤条件有:
- 在符合要求的 store 里面,选出最适合搬走副本的 store, 按照 region_score 倒叙排序, 优先考虑的条件有:
-
选择要搬走的副本,从当前选中的 source store 中选择一个副本,选择条件按优先级如下:
- pending regions
- followers
- Leaders
- Learners
-
选择一个目标 store 作为当前副本的目标
- 通过 placement-rule 选择符合要求的 store
- 检查 store limit add-peer ( https://docs.pingcap.com/tidb/stable/configure-store-limit#principles-of-store-limit-v2 )
- 检查 max-snapshot-count ( https://docs.pingcap.com/tidb/stable/pd-configuration-file#max-snapshot-count )
- 检查 max-pending-peer-count ( https://docs.pingcap.com/tidb/stable/pd-configuration-file#max-pending-peer-count )
- 最后对以上条件都符合的目标 store , 选择 region_score 最小的那个节点
常见问题
接下来,我们将根据上文说的调度生成的顺序,来介绍过程中可能遇到的问题及解决方案。
scheduler 被关闭导致没有调度生成
默认情况下 balance-region-scheduler 会被启用,但确实能够用 pd-ctl 将其删除。当发现没有 balance-region operator 生成时,第一步需要检查的便是确认 balance-region-scheduler 是否被启用。
- 通过监控查看 balance-region-scheduler 是否被启用,即调度发生的频率:
- PD->scheduler->scheduler is running
- 通过 pd-ctl 查看当前正在运行的 schedule
- 编辑 balance-region-scheduler
// remove balance-region-scheduler
~$ tiup ctl:v7.5.2 pd schedule remove balance-region-scheduler
Starting component ctl: /home/tidb/.tiup/components/ctl/v7.5.2/ctl pd schedule remove balance-region-scheduler Success!
// add balance-region-scheduler
~$ tiup ctl:v7.5.2 pd schedule add balance-region-scheduler
Starting component ctl: /home/tidb/.tiup/components/ctl/v7.5.2/ctl pd schedule add balance-region-scheduler Success! The scheduler is created."
受限于 region-schedule-limit
region-schedule-limit 是用来控制 balance-region / scatter-range/hot-region 等 region 相关的 operator 生成的并发度的,默认值是 2048,一般很难到达瓶颈。但考虑到这个参数是可以修改的,有时候误操作会将这个参数改得比较小,就容易出现问题。
- 通过 pd-ctl 检查及设置
// check config
tidb@~:~$ tiup ctl:v7.5.2 pd config show
Starting component ctl: /home/tidb/.tiup/components/ctl/v7.5.2/ctl pd config show
{....."schedule": {.... "max-movable-hot-peer-size": 512,"max-pending-peer-count": 64,"max-snapshot-count": 64,"max-store-down-time": "30m0s","max-store-preparing-time": "48h0m0s","merge-schedule-limit": 0,"patrol-region-interval": "10ms","region-schedule-limit": 2048,.... }
}// update region-schedule-limit
tidb@~:~$ tiup ctl:v7.5.2 pd config set region-schedule-limit 1024
Starting component ctl: /home/tidb/.tiup/components/ctl/v7.5.2/ctl pd config set region-schedule-limit 1024
Success!
- 通过监控看是否遇到瓶颈: PD ->operator->schedule reach limit
检查要被 move peer 的 store
一般在 scale out 的过程中,已用空间比较大的 store 很容易被选为 balance-region 的目标对象,因此已用空间比较大的那个 store 很容易受到 store limit remove-peer 的影响。
- 通过监控查看 store limit 配置:PD->cluster->PD scheduler config/store limit
- Store limit remove peer 不足的场景:PD->scheduler->filter source 看到大量的 balance-region-XXX-remove-limit 时:
检查待 add peer 的 store
在扩容场景下,这类 store 往往是新扩容的节点,因此这些新节点很容易变成热点,相关配置也比较容易到达使用瓶颈。这里相关配置主要是以下三个:
- store limit add-peer ( https://docs.pingcap.com/tidb/stable/configure-store-limit#principles-of-store-limit-v2 ) : speed limit for the special store
- max-snapshot-count ( https://docs.pingcap.com/tidb/stable/pd-configuration-file#max-snapshot-count ) : when the number of snapshots that a single store receives or sends meet the limit, it will never be chosen as a source or target store
- max-pending-peer-count ( https://docs.pingcap.com/tidb/stable/pd-configuration-file#max-pending-peer-count ): control the maximum number of pending peers in a single store.
- Metrics 中查看配置项(同 source store 配置项查看):pd->cluster->pd scheduler config/store limit
- 查看目标节点配置项是否遇到瓶颈:pd->schedule -> filter target -> balance-regionXXX-{config}-filter
生成 operator 的速度
经过以上步骤,一个 balance region 的 operator 变生成了。我们可以通过 pd->operator->schedule operator create -> balance region 查看当前 operator 的产生速度.
Summary
PD 生成 balance region operator 的速度,直接影响整个扩容的速度。为了保证 PD 在生成 operator 的速度不会成为瓶颈,我们可以根据上文中的监控来确定以下配置项是否设置合理,进行适当的调优:
- ensure balance-region-scheduler is running
- region-schedule-limit ( https://docs.pingcap.com/tidb/v7.5/pd-configuration-file#region-schedule-limit ) :control the generation speed of schedule-region operator
- store limit remove-peer/add-peer ( https://docs.pingcap.com/tidb/stable/configure-store-limit#principles-of-store-limit-v2 ) : speed limit for the special store
- max-snapshot-count ( https://docs.pingcap.com/tidb/stable/pd-configuration-file#max-snapshot-count ) : when the number of snapshots that a single store receives or sends meet the limit, it will never be choosed as a source or target store
- max-pending-peer-count ( https://docs.pingcap.com/tidb/stable/pd-configuration-file#max-pending-peer-count ): control the maximum number of pending peers in a single store.
如何判断当前扩容的瓶颈在 TiKV 还是在 PD 上
我们可以通过对比 PD 上的以上两个监控:
- PD->operators->schedule operator create
- PD->operators->schedule operator finish
来判断 operator 的消费速度能否跟得上生成速度,如果不能,说明 TiKV 中出现了瓶颈,则需要继续从 TiKV 中去寻找答案。
相关文章:

TiDB 扩容过程中 PD 生成调度的原理及常见问题丨TiDB 扩缩容指南(一)
导读 作为一个分布式数据库,扩缩容是 TiDB 集群最常见的运维操作之一。本系列文章,我们将基于 v7.5.0 具体介绍扩缩容操作的具体原理、相关配置及常见问题的排查。 通常,我们根据当前资源状态来决定是否需要调整 TiKV 节点的规模࿰…...

匿名管道详解
进程间通讯的目的 数据传输:一个进程需要把它的数据发送给另一个数据资源共享:多个进程需要共享同样的资源通知事件:一个进程需要向另一个或者一组进程发送消息,通知它发生了某种事件(如进程终止时要通知父进程&#…...

深度解读MySQL意向锁的工作原理机制与应用场景
意向锁 意向锁的概念 意向锁是InnoDB自动添加的一种锁,不需要用户去干预。 是数据库中的一种表级锁,一个事务要给一个资源加锁时,必须要先获取到对应类型的意向锁之后,才可以给这个资源加上自己想要的共享锁或者排他锁࿰…...
ZYNQ TCP 协议的远程更新 QSPI Flash
1 SDK直接少些Flash过程 ****** Xilinx Program Flash ****** Program Flash v2019.1 (64-bit)**** SW Build 2552052 on Fri May 24 14:49:42 MDT 2019** Copyright 1986-2019 Xilinx, Inc. All Rights Reserved.WARNING: Failed to connect to hw_server at TCP:127.0.0.1:3…...

告别繁琐粘贴,CleanClip Mac 版,让复制粘贴变得简单快捷!粘贴队列功能太强大了!
告别繁琐粘贴,CleanClip Mac 版,让复制粘贴变得简单快捷! CleanClip for Mac 📋 是一款专为Mac用户设计的高效剪贴板管理工具。它解决了传统复制粘贴过程中的繁琐问题,让你的工作流程更加顺畅和高效。 🔄…...

前端基础知识(HTML+CSS+JavaScript)
文章目录 一、HTML1.1 HTML 基础:1.1.1 HTML 的概念:1.1.2 认识 HTML 标签:1.1.3 HTML 文件基本结构:1.1.4 标签层次结构: 1.2 HTML 快速入门:1.3 HTML常见标签:1.3.1 标题标签:h1-h…...
算力服务器和GPU服务器的区别是什么?
随着互联网科技的快速发展,服务器的类型也变得多种多样了,今天小编就来为大家介绍一下算力服务器和GPU服务器还有他们之间的区别是什么? 算力服务器通常是指具有着较高计算能力的服务器,算力服务器一般都是用于处理大量的计算任务…...

获取Live2d模型
文章目录 1、 Live2D官方示例数据集(可免费下载)2、模之屋3、unity商店4、直接b站搜索5、youtube6、BOOTH完结 1、 Live2D官方示例数据集(可免费下载) 官方提供了一些 Live2D实例模型给大家下载使用 地址:https://ww…...

软考架构-层次架构风格
一、两层C/S架构 客户端和服务器都有处理功能。处理在表示层(客户端)和数据层(服务器)进行 二、三层C/S架构 将处理功能独立出来。表示层在客户机上,功能层在应用服务器上,数据层在数据库服务器上。 三…...

Unity射击游戏开发教程:(35)轰炸敌人
现在敌人和飞机已经慢慢地越来越有各自地地行为了,在本文中,我们将介绍如何创建一个具有以下行为的敌人: 飞机会来回弹跳。飞机将有 4 架无人机轰炸机围绕飞机旋转。无人机轰炸机会偶尔投下沿着屏幕传播的炸弹。如果炸弹击中玩家或在随机时间后就会爆炸。如果炸弹没有击中玩…...

【网络】高级IO——select版本TCP服务器
目录 前言 一,select函数 1.1.参数一:nfds 1.2.参数二: readfds, writefds, exceptfds 1.2.1.fd_set类型和相关操作宏 1.2.2.readfds, writefds, exceptfds 1.2.3.怎么理解 readfds, writefds, exceptfds是输入输出型参数 1.3.参数三…...

【C++】学完c语言后的c++基础知识补充!(命名空间、输入和输出、缺省函数、函数重载、引用、内联函数代替宏、nullptr代替NULL)
一. 命名空间 1. 定义 出现的意义:解决各种函数、关键词和类的名称冲突问题。 定义方式:namespace 命名空间的名字 { } (注意!}后面不加;) namespace 是关键词命名空间的…...
uniapp自定义导航栏以及页面加背景
如果想给uniapp的页面加背景图片的话,疯狂度了之后会发现uniapp中背景图片用本地图片不起效果,所以一般用网络路径,之后又会发现,页面如果直接加背景的话有可能会遇到页面内容不够,背景撑不满整个页面,如果…...

MacOS Sonoma(14.x) 大写模式或中文输入法下的英文模式,光标下方永远会出现的CapsLock箭头Icon的去除办法
如图,MacOS Sonoma(14.x) 大写模式或中文输入法下的英文模式下,光标下方永远会出现一个CapsLock箭头Icon。此Icon挡住视野,还容易误触导致切换大小写状态,带来的收益远远小于带来的困扰。 解决办法 打开终端,输入以下…...
C#基础(10)变长参数和参数默认值
前言 作为函数的补充知识点,我们已经学习了ref和out,接下来两节我们继续来讲函数相关的内容。本节则讲解变长参数和参数默认值。 函数语法 关键字:params public void PrintNumbers(params int[] numbers) {for 相关逻辑 } 注意 params…...
Vue转React开发经验分享——hooks写法如何触发react生命周期、如何触发数据更新?
背景:习惯了vue的写法,并且vue2和vue3都比较熟悉,在转react开发中,不停的思考react和vue框架的相似之处,以及vue中的写法在react里怎么替换。本文将组件更新或组件生命周期角度出发聊聊如何使用hooks触发生命周期&…...

算法入门-贪心1
第八部分:贪心 409.最长回文串(简单) 给定一个包含大写字母和小写字母的字符串 s ,返回通过这些字母构造成的最长的回文串 的长度。 在构造过程中,请注意 区分大小写 。比如 "Aa" 不能当做一个回文字符串…...

element-plus的面包屑组件el-breadcrumb
面包屑组件主要用来显示当页面路径,以及快速返回之前的页面。 涉及2个组件 el-breadcrumb 和el-breadcrumb-item, el-breadcrumb的spearator指定item的分隔符 el-breadcrumb-item的to和replace属性和vue-router的一致,需要结合vue_router一起使用 用法…...
推荐几个网盘资源站给大伙,找资源更方便
夸克网盘在当前已然成为极为主流的网盘之一,其功能体验堪称强大,不仅支持在线解压阅读,磁力离线等功能也十分出色。那么,究竟该如何寻找夸克资源呢?下面,我就来为大家分享几个堪称神级的夸克资源网站。 一、…...

【Qt】Qml界面中嵌入C++ Widget窗口
1. 目的 qml做出的界面漂亮,但是执行效率低,一直想找一个方法实现qml中嵌入c界面。现在从网上找到一个方法,简单试了一下貌似可行,分享一下。 2. 显示效果 3. 代码 3.1 工程结构 3.2 pro文件 需要添加widgets > QT quick …...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...

深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...