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

Redis 集群

集群基本介绍

广义的集群,只要是多个机器构成了分布式系统,都可以称为是一个“集群”(主从模式,哨兵模式)

狭义的集群,Redis 提供的集群模式,在这个模式下主要解决的是存储空间不足的问题(拓展存储空间)

引入多组 master/slave,每一组 master/slave 存储数据全集的一部分,从而构成一个更大的整体

——>  Redis 集群  Cluster

每一组 master/slave 都可以称为是一个 分片  sharding

如果全量数据进一步增加,只需要增加更多的分片即可

数据分片算法

1)哈希求余

借助 hash 函数(例如 MD5),把一个 key 映射到整数,再针对数组的长度求余,得到一个数组的下标

MD5 本身就是一个计算 hash 值的算法,针对一个字符串里面的内容进行一系列的数学转换,最后得到一个 整数(十六进制)

1)md5 计算结果是定长的

无论输入的字符串多长,最终算出的结果就是固定长度

2)md5 计算结果是分散的 [哈希函数]

两个原字符串哪怕只有一小部分不一样,算出的 md5 值也会差别很大

3)md5 计算结果是不可逆的 [加密]

根据原字符串,容易计算 md5 值;根据 md5 值,理论上还原不出原字符串

hash(key) % N => 0    这个 key 就要存储到 0 号分片中

后续查询 key 时,也是相同的算法

随着业务数据的增长,原先的分片不足以保存了,就需要“扩容”——>

引入新的分片,N 就改变了    hash(key) % N  就不一定等于 0 了

在扩容后,如果发现某个数据不应该在当前的分片中,就需要重新分配了(搬运数据)

可以看出,上述 20 个数据,只有 3 个不需要搬运,那如果是 20 亿个数据?

上述级别的扩容,开销极大往往是不能直接在生产环境上操作的,只能通过“替换”的方式来实现扩容的

2)一致性哈希算法

在 哈希求余 这种操作中,当前 key 的分片是 交替 的

在 一致性哈希 的设定下,改进成 连续出现

1.把 0 ~ 2*32 -1 映射到一个圆环上,数据按照顺时针增长

2.假设当前存在三个分片,把分片均匀地放到圆环上

3.根据 key 计算 hash 值,再根据 hash 值 进行分片

扩容后——>

只需要把 0号分片 上的这一段数据搬运到 3号分片 即可

其余的分片都是不变的,搬运成本明显降低,但是不同分片上的的数据量就不均匀了(数据倾斜)

3)哈希槽分区算法

Redis 真正采用的是 哈希槽分区算法(hash slots)

hash_slot = crc16(key) % 16384        16384 = 16 * 1024 = 2 *14

相当于是把整个哈希值,映射到 16384 个槽位上,也就是 [0, 16384]

假设有三个分片:

~0号分片:[0, 5461],共5462个槽位

~1号分片:[5462, 10923],共5462个槽位

~2号分片:[10924, 16384],共5460个槽位

虽然不是严格的“均匀”,但是差异非常小,此时三个分片上的数据就是比较均匀的

以上只是一种可能的分片方式,每个分片持有的槽位号,可以是连续的,也可以是不连续的

每个分片,会使用“位图”这样的数据结构表示当前持有多少槽位号

16384个bit位,用每一位0/1来区分是否持有每一槽号位

对于16384个bit位,约需要 2kb 的空间

扩容后——>

~0号分片:[0, 4095],共5462个槽位

~1号分片:[5462, 9557],共5462个槽位

~2号分片:[10924, 15019],共5462个槽位

~3号分片:[4096, 5461] + [9558, 10923] + [15019, 16383],共5462个槽位

在上述过程中,只有被移动的槽位,对应的数据才需要搬运

针对某分片上的槽位号,不一定非得是连续的区间

Redis 中,当前某个分片包含的那些槽位都是可以手动配置的

1)Redis 集群中最多可以有 16384个分片吗?

如果每个分片只有一个槽位,对于集群的数据均匀是难以保证的

因此,Redis 的作者建议集群分片数不应该超过1000(可用性)

2)为什么是16384个槽位?

hehzuozzuozuzhttps://github.com/antirez/redis/issues/2576

 节点之间通过心跳包通信. 心跳包中包含了该节点持有哪些 slots. 这个是使用位图这样的数据结构表示的. 表示 16384 (16k) 个 slots, 需要的位图大小是 2KB. 如果给定的 slots 数更多了, 比如 65536个了, 此时就需要消耗更多的空间, 8 KB 位图表示了. 8 KB, 对于内存来说不算什么, 但是在频繁的网络心跳包中, 还是一个不小的开销的.
•  另⼀方面, Redis 集群一般不建议超过 1000 个分片. 所以 16k 对于最大 1000 个分片来说是足够用的, 同时也会使对应的槽位配置位图体积不至于很大

搭建集群环境

1)创建目录和配置

  在 generate.sh 中写入 shell 脚本

执行脚本后生成的目录(蓝色):

cluster-enabled yes:开启集群
cluster-config-file nodes.conf:集群节点生成的配置
cluster-node-timeout 5000:节点失联的超超时信息
cluster-announce-ip 172.30.0.101:节点自身IP(静态IP)
该 Redis 节点所在的主机的IP(当前是使用 docker 容器模拟的主机,此处写的是 docker 容器的IP)
Redis 节点自身绑定的端口(容器内端口),不同的容器内部可以有相同的接口
后续进行端口映射,再把这些容器内的端口映射到容器外的不同端口
cluster-announce-port 6379:节点自身的业务端口
cluster-announce-bus-port 16379:节点自身的总线端口(集群管理的信息交互是通过这个端口进行的)

业务端口:进行业务通信,响应 Redis 客户端的请求

管理端口:完成一些管理上的任务来进行通信(某个分片中从节点的晋升)

一个服务器,可以绑定多个端口

2)编写 docker-compose.yml

将下面的配置添加到 docker-compose.yml 中(注意缩进)

version: '3.7'
networks:
 mynet:
 ipam:
 config:
 - subnet: 172.30.0.0/24
services:
 redis1:
 image: 'redis:5.0.9'
 container_name: redis1
 restart: always
 volumes:
 - ./redis1/:/etc/redis/
 ports:
 - 6371:6379
 - 16371:16379
 command:
 redis-server /etc/redis/redis.conf
 networks:
 mynet:
 ipv4_address: 172.30.0.101
 redis2:
 image: 'redis:5.0.9'
 container_name: redis2
 restart: always
 volumes:
 - ./redis2/:/etc/redis/
 ports:
 - 6372:6379
 - 16372:16379
 command:
 redis-server /etc/redis/redis.conf
 networks:
 mynet:
 ipv4_address: 172.30.0.102
 redis3:
 image: 'redis:5.0.9'
 container_name: redis3
 restart: always
 volumes:
 - ./redis3/:/etc/redis/
 ports:
 - 6373:6379
 - 16373:16379
 command:
 redis-server /etc/redis/redis.conf
 networks:
 mynet:
 ipv4_address: 172.30.0.103
 redis4:
 image: 'redis:5.0.9'
 container_name: redis4
 restart: always
 volumes:
 - ./redis4/:/etc/redis/
 ports:
 - 6374:6379
 - 16374:16379
 command:
 redis-server /etc/redis/redis.conf
 networks:
 mynet:
 ipv4_address: 172.30.0.104
 redis5:
 image: 'redis:5.0.9'
 container_name: redis5
 restart: always
 volumes:
 - ./redis5/:/etc/redis/
 ports:
 - 6375:6379
 - 16375:16379
 command:
 redis-server /etc/redis/redis.conf
 networks:
 mynet:
 ipv4_address: 172.30.0.105
 redis6:
 image: 'redis:5.0.9'
 container_name: redis6
 restart: always
 volumes:
 - ./redis6/:/etc/redis/
 ports:
 - 6376:6379
 - 16376:16379
 command:
 redis-server /etc/redis/redis.conf
 networks:
 mynet:
 ipv4_address: 172.30.0.106
 redis7:
 image: 'redis:5.0.9'
 container_name: redis7
 restart: always
 volumes:
 - ./redis7/:/etc/redis/
 ports:
 - 6377:6379
 - 16377:16379
 command:
 redis-server /etc/redis/redis.conf
 networks:
 mynet:
 ipv4_address: 172.30.0.107
 redis8:
 image: 'redis:5.0.9'
 container_name: redis8
 restart: always
 volumes:
 - ./redis8/:/etc/redis/
 ports:
 - 6378:6379
 - 16378:16379
 command:
 redis-server /etc/redis/redis.conf
 networks:
 mynet:
 ipv4_address: 172.30.0.108
 redis9:
 image: 'redis:5.0.9'
 container_name: redis9
 restart: always
 volumes:
 - ./redis9/:/etc/redis/
 ports:
 - 6379:6379
 - 16379:16379
 command:
 redis-server /etc/redis/redis.conf
 networks:
 mynet:
 ipv4_address: 172.30.0.109
 
 redis10:
 image: 'redis:5.0.9'
 container_name: redis10
 restart: always
 volumes:
 - ./redis10/:/etc/redis/
 ports:
 - 6380:6379
 - 16380:16379
 command:
 redis-server /etc/redis/redis.conf
 networks:
 mynet:
 ipv4_address: 172.30.0.110
 redis11:
 image: 'redis:5.0.9'
 container_name: redis11
 restart: always
 volumes:
 - ./redis11/:/etc/redis/
 ports:
 - 6381:6379
 - 16381:16379
 command:
 redis-server /etc/redis/redis.conf
 networks:
 mynet:
 ipv4_address: 172.30.0.111

此处为了后续创建静态 IP,需要先手动创建出网络,同时给这个网络也分配 IP

网络原理-IP 协议-IP 地址规则

IP 地址 = 网络号 + 主机号

使用子网掩码区分网络号和主机号

ipv4_address:此处也可以不进行端口映射

映射的目的是为了在容器外面通过客户端直接进行访问

此处配置静态IP

网络号要和之前的网段一致,主机号可以随意配置

3)启动容器

docker-compose up -d

在启动容器前,要确保之前的 redis 都被干掉

ps aux | grep redis

查看 Redis 相关进程

docker ps -a

查看 容器

4)构建集群

在命令行中执行以下命令

redis-cli --cluster create 172.30.0.101:6379 172.30.0.102:6379
172.30.0.103:6379 172.30.0.104:6379 172.30.0.105:6379 172.30.0.106:6379
172.30.0.107:6379 172.30.0.108:6379 172.30.0.109:6379 --cluster-replicas 2

--cluster create:表示建立集群,后面填写每个节点的 IP 和 地址

--cluster-replicas 2:表示每个主节点需要两个从节点备份

从 101 ~ 109 九个节点现在是一个整体,使用客户端上的任意一个节点,本质上是等价的

连接 Redis 客户端:

redis-cli -h 172.30.0.101 -p 6379  静态 IP

redis-cli -p 6379  端口映射

cluster nodes  查看当前集群的信息

设置成集群模式后,当前数据就分片了

key1 通过 hash 计算后,属于 102 这个分片,在当前分片 101 上不能设置

可以在启动 redis-cli 时,加上 -c 选项

此时客户端发现当前 key 不再当前分片上,会自动重定向到对应的分片主机上

使用集群后,之前学的命令大多都可以正常使用(可以使用 hash tag ..处理特殊情况)

故障处理

docker stop redis    停止节点

docker start redis    启动节点

在集群中,从节点挂了,影响不大;主节点挂了,会自动把该主节点下的从节点,挑选一个晋升成主节点(类似于 哨兵)

集群机制,也能处理故障转移,但是此处的处理流程和 哨兵 不太一样

1)故障判定

集群中的所有节点, 都会周期性的使用心跳包进行通信.
1. 节点 A 给 节点 B 发送 ping 包, B 就会给 A 返回⼀个 pong 包. ping 和 pong 除了 message type
属性之外, 其他部分都是一样的. 这里包含了集群的配置信息(该节点的id, 该节点从属于哪个分片,
是主节点还是从节点, 从属于谁, 持有哪些 slots 的位图...)
2. 每个节点, 每秒钟, 都会给一些随机的节点发起 ping 包, ⽽不是全发⼀遍. 这样设定是为了避免在节点很多的时候, 心跳包也非常多(比如有 9 个节点, 如果全发, 就是 9 * 8 有 72 组心跳了, 而且这是按照 N^2 这样的级别增长的)
3. 当节点 A 给节点 B 发起 ping 包, B 不能如期回应的时候, 此时 A 就会尝试重置和 B 的 tcp 连接, 看能否连接成功. 如果仍然连接失败, A 就会把 B 设为 PFAIL 状态(相当于主观下线).
4. A 判定 B 为 PFAIL 之后, 会通过 redis 内置的 Gossip 协议, 和其他节点进行沟通, 向其他节点确认 B的状态. (每个节点都会维护一个自己的 "下线列表", 由于视角不同, 每个节点的下线列表也不一定相同)
5. 此时 A 发现其他很多节点, 也认为 B 为 PFAIL, 并且数目超过总集群个数的一半, 那么 A 就会把 B 标记成 FAIL (相当于客观下线), 并且把这个消息同步给其他节点(其他节点收到之后, 也会把 B 标记成FAIL)至此, B 就彻底被判定为故障节点了
核心原则是保证每个 slots 都能正常工作(存取数据)

2)故障转移

上述例子中, B 故障, 并且 A 把 B FAIL 的消息告知集群中的其他节点.

 如果 B 是从节点, 那么不需要进行故障迁移.
•  如果 B 是主节点, 那么就会由 B 的从节点 (比如 C 和 D) 触发故障迁移了
所谓故障迁移, 就是指把从节点提拔成主节点, 继续给整个 redis 集群提供支持
具体流程如下:
1. 从节点判定自己是否具有参选资格. 如果从节点和主节点已经太久没通信(此时认为从节点的数据和主节点差异太大了), 时间超过阈值, 就失去竞选资格
2. 具有资格的节点, 比如 C 和 D, 就会先休眠一定时间. 休眠时间 = 500ms 基础时间 + [0, 500ms] 随机时间 + 排名 * 1000ms. offset 的值越大, 则排名越靠前(越小)
3. 比如 C 的休眠时间到了, C 就会给其他所有集群中的节点, 进行拉票操作. 但是只有主节点才有投票资格
4. 主节点就会把自己的票投给 C (每个主节点只有 1 票). 当 C 收到的票数超过主节点数目的一半, C 就会晋升成主节点. (C 自己负责执行 slaveof no one, 并且让 D 执行 slaveof C).
5. 同时, C 还会把自己成为主节点的消息, 同步给其他集群的节点. 大家也都会更新自己保存的集群结构信息
上述选举的过程, 称为 Raft 算法, 是一种在分布式系统中广泛使用的算法
在随机休眠时间的加持下, 基本上就是谁先唤醒, 谁就能竞选成功

3)集群宕机

某个或者某些节点宕机, 有的时候会引起整个集群都宕机 (称为 fail 状态)
以下三种情况会出现集群宕机:
某个分片, 所有的主节点和从节点都挂了.
某个分片, 主节点挂了, 但是没有从节点.
超过半数的 master 节点都挂了

集群扩容

当前的集群中,有 101 ~ 109,9个主机,形成 3主,6从的结构

现在把 110 和 111 也加入到集群中,110 为 master,111为 slave,数据分片 3 ——> 4

1)把新的节点加入到集群中

redis-cli --cluster add-node 172.30.0.110:6379 172.30.0.101:6379
add-node 后的第一组地址是新节点的地址,第二组地址是集群中的任意节点的地址

2)重新分配 slots

redis-cli --cluster reshard 172.30.0.101:6379
reshard 后的地址是集群中的任意节点的地址
执行之后, 会进入交互式操作, redis 会提示用户输入以下内容:
多少个 slots 要进行 reshard ? (此处填写 4096)
哪个节点来接收这些 slots ? (此处填写 172.30.0.110 这个节点的集群节点 id)
这些 slots 从哪些节点搬运过来? (此处填写 all)
all:表示从其他每个持有 slots 的 master 都拿过来点
手动指定:从某个或者某几个节点来移动 slots(以 done 结尾)
输入 all 之后,会给出搬运计划(还没有真正搬运),当输入 yes 之后,搬运真正开始 ——>
重新划分 slots,把 slots 对应上的数据也搬运到新主机上(比较重量级的操作)
在搬运 slots / key 的过程中,客户端能否访问 Redis 集群?
大部分的 key 不需要搬运,针对这些未搬运的 key,此时可以正常访问
针对正在搬运的 key,是有可能出现访问出错的情况

追求更高的可用性,减少对用户的影响 ——>

搞一组新的机器,重新搭建集群,并且把数据导入进来,使用新的集群替代旧的集群(成本最高)

3)给新的主节点添加从节点

redis-cli --cluster add-node 172.30.0.111:6379 172.30.0.101:6379 --cluster
slave --cluster-master-id [172.30.1.110 节点的 nodeId]
集群的缩容
1)删除从节点
redis-cli --cluster del-node [ 集群中任一节点 ip:port] [ 要删除的从机节点 nodeId]
2)重新分配 slots
redis-cli --cluster reshard 172.30.0.101:6379
3)删除主节点
redis-cli --cluster del-node [ 集群中任一节点 ip:port] [ 要删除的从机节点 nodeId]

相关文章:

Redis 集群

集群基本介绍 广义的集群,只要是多个机器构成了分布式系统,都可以称为是一个“集群”(主从模式,哨兵模式) 狭义的集群,Redis 提供的集群模式,在这个模式下主要解决的是存储空间不足的问题&…...

【Redis】基础命令数据结构

文章目录 基础命令keysexistsdelexpirettltype 数据结构和内部编码 在介绍数据类型前先介绍一下 Redis 的基础命令,方便理解 基础命令 keys 返回所有满足样式(pattern)的 key keys pattern 当前有如下 key PS:实际开发环境和生…...

C++(6):逻辑运算符

目录 1. 代码示例 示例 1:基础用法 示例 2:条件判断 2. 短路求值(Short-Circuit Evaluation) 代码示例 3. 实际应用场景 场景 1:输入合法性验证 场景 2:游戏状态判断 4. 注意事项 逻辑运算符用于组…...

项目管理从专家到小白

敏捷开发 Scrum 符合敏捷开发原则的一种典型且在全球使用最为广泛的框架。 三个角色 产品负责人Product Ower:专注于了解业务、客户和市场要求,然后相应地确定工程团队需要完成的工作的优先顺序。 敏捷教练Scrum Master:确保 Scrum 流程顺…...

AI绘画灵感觉醒指南:从灵感源泉到创意输出

目录 一、引言 二、灵感来源 2.1 现实生活 2.2 其他艺术作品 2.3 文学作品 三、灵感转化为输入提示 3.1 明确主题与核心元素 3.2 细化描述 3.3 使用修饰词与专业术语 3.4 组合与优化提示词 四、案例分析 4.1 从现实生活获取灵感 4.2 从其他艺术作品获取灵感 4.3 …...

【Java学习】枚举(匿名类详解)

目录 一、匿名类 1.形式 2.性质 2.1匿名性 2.1.1同步性 使用场景 2.1.2复用性 2.1.3向上转型 2.2实现性 3.传参 3.1构造传全参 3.1.1过程 3.1.2效果 2.1.4原子类构造无参 4.权限 二、枚举类 1.枚举常量 2.性质 2.1多态性 2.2单例性 2.2.1private保护 2.2…...

力扣题解:2、两数相加

个人认为,该题目可以看作合并两个链表的变种题,本题与21题不同的是,再处理两个结点时,对比的不是两者的大小,而是两者和是否大于10,加法计算中大于10要进位,所以我们需要声明一个用来标记是否进…...

PyTorch API 9 - masked, nested, 稀疏, 存储

文章目录 torch.randomtorch.masked简介动机什么是 MaskedTensor? 支持的运算符一元运算符二元运算符归约操作查看与选择函数 torch.nested简介构造方法数据布局与形状支持的操作查看嵌套张量的组成元素填充张量的相互转换形状操作注意力机制 与 torch.compile 的配…...

linux测试硬盘读写速度

#!/bin/bash # 文件名: disk_rate.sh # linux测试硬盘读写速度 TEST_FILE"disk_speed_test.tmp" TEST_SIZE"1024M" echo "开始测试磁盘写入速度..." WRITE_RESULT$(dd if/dev/zero of$TEST_FILE bs$TEST_SIZE count1 oflagdirect 2…...

单片机系统设计不同开发方式的优缺点(面包板,洞洞板,PCB板)

目录 快速验证代码逻辑 涉及具体电路较多 涉及高频电路 快速验证代码逻辑 面包板,无焊接,适合快速搭建临时电路。优点应该是使用方便,不需要焊接,可以随时更换元件。但缺点可能是不稳定,接触不良,不适合高…...

数字信号处理|| 快速傅里叶变换(FFT)

一、实验目的 (1)加深对快速傅里叶变换(FFT)基本理论的理解。 (2)了解使用快速傅里叶变换(FFT)计算有限长序列和无限长序列信号频谱的方法。 (3)掌握用MATLA…...

基于CNN卷积神经网络的带频偏QPSK调制信号检测识别算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2024b 3.部分核心程序 (完整版代码包含详细中文注释和操作步骤视频&#xff09…...

数据库索引详解:原理 · 类型 · 使用 · 优化

在关系型数据库中,索引(Index)是提高查询性能的利器。合理设计和使用索引,可以极大地减少 IO 操作,提升查询效率;但滥用或误用索引,却可能带来维护开销和性能瓶颈。我将从以下几个方面&#xff…...

Java大数据可视化在城市空气质量监测与污染溯源中的应用:GIS与实时数据流的技术融合

随着城市化进程加速,空气质量监测与污染溯源成为智慧城市建设的核心议题。传统监测手段受限于数据离散性、分析滞后性及可视化能力不足,难以支撑实时决策。2025年4月27日发布的《Java大数据可视化在城市空气质量监测与污染溯源中的应用》一文&#xff0c…...

【基于 LangChain 的异步天气查询3】OpenWeather实现实时天气查询

目录 一、项目功能概述 1、城市识别(GeoNames API) 2、天气数据获取(OpenWeather API) 3、AI 分析天气(deepseek-r1) 4、异步运行支持 5、配置文件隔离(.env) 二、注册 OpenW…...

.Net HttpClient 管理客户端(初始化与生命周期管理)

HttpClient 初始化与生命周期管理 HttpClient 旨在实例化一次,并在应用程序的整个生命周期内重复使用。 为实现复用,HttpClient类库默认使用连接池和请求管道,可以手动管理(连接池、配置管道、使用Polly); 结合IoC容器、工厂模式(提供了IHt…...

树莓派4的v4l2摄像头(csi)no cameras available,完美解决

根据2025年最新技术文档和树莓派官方支持建议,no cameras available错误通常由驱动配置冲突或硬件连接问题导致。以下是系统化解决方案: 一、核心修复步骤 强制禁用传统驱动 sudo nano /boot/firmware/config.txt确保包含以下配置(2025年新版…...

VBA将PDF文档内容逐行写入Excel

VBA是无法直接读取PDF文档的,但结合上期我给大家介绍了PDF转换工具xpdf-tools-4.05,先利用它将PDF文档转换为TXT文档,然后再将TXT的内容写入Excel,这样就间接实现了将PDF文档的内容导入Excel的操作。下面的代码将向大家演示如何实…...

【STM32 学习笔记】USART串口

注意:在串口助手的接收模式中有文本模式和HEX模式两种模式,那么它们有什么区别?   文本模式和Hex模式是两种不同的文件编辑或浏览模式,不是完全相同的概念。文本模式通常是指以ASCII编码格式表示文本文件的编辑或浏览模式。在文…...

位图布隆过滤器

1.位图 所谓位图,就是用每一位来存放某种状态,适用于海量数据,整数,数据无重复的场景。通常是用来判 断某个数据存不存在的。 如上例子,10个整数本应该存放需要40个字节,此时用位图只需要3个字节。 下面代…...

【Web】使用Vue3开发鸿蒙的HelloWorld!

文章目录 1、简介2、效果3、环境3.1、开发环境3.2、运行环境 4、实现4.1、在VSCode上使用Vue开发HelloWorld4.1.1、通过 Vite 快速创建项目4.1.2、修改 src/App.vue4.1.3、模拟Web浏览器运行 4.2、使用DevEco完成手机App端移植4.2.1、构建Vue 3项目为静态文件4.2.2、创建Harmon…...

cv_area_center()

主题 用opencv实现了halcon中area_center算子的功能, 返回region的面积,中心的行坐标和中心的列坐标 代码很简单 def cv_area_center(region):area[]row []col []for re in region:retval cv2.moments(re)area.append(retval[m00])row.append(int(r…...

Python+OpenCV实现手势识别与动作捕捉:技术解析与应用探索

引言:人机交互的新维度 在人工智能与计算机视觉技术飞速发展的今天,手势识别与动作捕捉技术正逐步从实验室走向大众生活。通过Python的OpenCV库及MediaPipe等工具,开发者能够以较低门槛实现精准的手部动作识别,为虚拟现实、智能家…...

【llama-factory】Lora微调和DPO训练

微调参考 DPO参考 llama-factory官网 LoRA微调 数据集处理 数据集格式和注册 Alpaca数据集格式: [{"instruction": "人类指令(必填)","input": "人类输入(选填)","…...

JS较底层的用法,几类简单介绍

JS较底层的用法 在 JavaScript 中,“偏底层”的用法通常是指更接近语言核心、规范、底层机制的特性。这些用法不是日常开发中最常见的,但对理解语言原理、优化性能或构建框架、库非常重要。下面是一些常见的“偏底层”用法或特性 1. 对象属性底层操作&am…...

当可视化遇上 CesiumJS:突破传统,打造前沿生产配套方案

CesiumJS 技术基础介绍 CesiumJS 是一款基于 JavaScript 的开源库,专门用于创建动态、交互式的地理空间可视化。它利用 WebGL 技术,能够在网页浏览器中流畅地渲染高分辨率的三维地球和地图场景。CesiumJS 支持多种地理空间数据格式,包括但不…...

使用python脚本连接SQL Server数据库导出表结构

一. 准备工作 Mac 系统安装freetds brew install freetds 安装pymssql pip3 install pymssql 二.导出指定表的结构: import pymssql# 配置数据库连接参数(根据实际情况修改) server # 内网服务器地址或IP database # 数据库名称…...

Docker基础入门

Docker核心概念 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。 容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app&#…...

day011-权限管理专题

文章目录 1. 对比文件内容1.1 diff1.2 vimdiff 2. /etc/skel目录3. 权限基础4. 修改权限4.1 用数字权限修改4.2 用字母修改权限(ugo)4.3 修改文件所有者和用户组 5. 文件与目录权限6. permission denied 权限拒绝7. 特殊权限8. 特殊属性9. 思维导图 1. 对…...

ragflow报错:KeyError: ‘\n “序号“‘

环境: ragflowv 0.17.2 问题描述: ragflow报错:KeyError: ‘\n “序号”’ **1. 推荐表(输出json格式)** [{"},{},{"},{} ]raceback (most recent call last): May 08 20:06:09 VM-0-2-ubuntu ragflow-s…...

基于FPGA的PID控制器verilog实现,包含simulink对比模型

目录 1.课题概述 2.系统测试效果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 根据PID控制器的原理,设计FPGA的总体架构。通常包括误差计算模块、比例运算模块、积分运算模块、微分运算模块、加法器模块以及控制信号输出模块等。同时通过simul…...

互联网大厂Java面试实录:Spring Boot与微服务架构在电商场景中的应用解析

💪🏻 1. Python基础专栏,基础知识一网打尽,9.9元买不了吃亏,买不了上当。 Python从入门到精通 😁 2. 毕业设计专栏,毕业季咱们不慌忙,几百款毕业设计等你选。 ❤️ 3. Python爬虫专栏…...

前端开发实战:用React Hooks优化你的组件性能

问题背景 在前端开发中,React组件的性能优化是一个常见挑战。尤其是当组件逻辑复杂或数据频繁更新时,性能问题尤为突出。本文将介绍如何利用React Hooks(如useMemo和useCallback)来优化组件性能。 解决方案 useMemo:用…...

Kotlin 内联函数深度解析:从源码到实践优化

一、内联函数核心概念 1. 什么是内联函数? 内联函数通过 inline 关键字修饰,其核心思想是:在编译时将函数体直接插入到调用处,而非进行传统的函数调用。这意味着: 消除了函数调用的栈帧创建、参数传递等开销。对 La…...

模拟太阳系(C#编写的maui跨平台项目源码)

源码下载地址:https://download.csdn.net/download/wgxds/90789056 本资源为用C#编写的maui跨平台项目源码,使用Visual Studio 2022开发环境,基于.net8.0框架,生成的程序为“模拟太阳系运行”。经测试,生成的程序可运行…...

python中的继承和多态

Python中的继承 继承中的一些基础的定义 继承是面向对象编程的三大特性之一,它允许一个类(子类)继承另一个类(父类)的属性和方法,从而实现代码的复用(继承的主要目的)和扩展。父类…...

【计算机视觉】3DDFA_V2中表情与姿态解耦及多任务平衡机制深度解析

3DDFA_V2中表情与姿态解耦及多任务平衡机制深度解析 1. 表情与姿态解耦的技术实现1.1 参数化建模基础1.2 解耦的核心机制1.2.1 基向量正交化设计1.2.2 网络架构设计1.2.3 损失函数设计 1.3 实现代码解析 2. 多任务联合学习的权重平衡2.1 任务定义与损失函数2.2 动态权重平衡策略…...

vue访问后端接口,实现用户注册

文章目录 一、后端接口文档二、前端代码请求响应工具调用后端API接口页面函数绑定单击事件,调用/api/user.js中的函数 三、参考视频 一、后端接口文档 二、前端代码 请求响应工具 /src/utils/request.js //定制请求的实例//导入axios npm install axios import …...

MySQL 从入门到精通(五):索引深度解析 —— 性能优化的核心武器

目录 一、索引概述:数据库的 “目录” 1.1 什么是索引? 1.2 索引的性能验证:用事实说话 实验环境准备 无索引查询耗时 有索引查询耗时 索引的 “空间换时间” 特性 二、索引的创建:三种核心方式 2.1 方式 1:C…...

湖北理元理律师事务所:债务优化如何实现还款与生活的平衡?

债务压力往往让债务人陷入“还款还是生存”的两难选择。湖北理元理律师事务所通过案例实践发现,科学规划的核心在于平衡法律义务与基本生活保障,而非单纯追求债务缩减。本文结合实务经验,解析债务优化的可行路径。 刚性需求优先:…...

Day21 奇异值分解(SVD)全面解析

一、奇异值分解概述 奇异值分解是线性代数中一个重要的矩阵分解方法,对于任何矩阵,无论是结构化数据转化成的“样本 * 特征”矩阵,还是天然以矩阵形式存在的图像数据,都能进行等价的奇异值分解(SVD)。 二…...

【vue】vuex实现组件间数据共享 vuex模块化编码 网络请求

目录 一、vuex实现组件间数据共享 二、 vuex模块化编码 三、网络请求 模块化命名空间小结: 总结不易~ 本章节对我有很大的收获, 希望对你也是!!! 本节素材已上传Gitee:yihaohhh/我爱Vue - Gitee.comhttps://gitee.…...

红黑树删除的实现与四种情况的证明

🧭 学习重点 删除节点的三种情况红黑树如何恢复性质四种修复情况完整可运行的 C 实现 一、红黑树删除的基础理解 红黑树删除比插入复杂得多,因为: 删除的是黑节点可能会破坏“从根到叶子黑节点数相等”的性质。删除红节点无需修复&#xf…...

FHE与后量子密码学

1. 引言 近年来,关于 后量子密码学(PQC, Post-Quantum Cryptography) 的讨论愈发热烈。这是因为安全专家担心,一旦有人成功研发出量子计算机,会发生什么可怕的事情。由于 Shor 算法的存在,量子计算机将能够…...

使用FastAPI和React以及MongoDB构建全栈Web应用04 MongoDB快速入门

一、NoSQL 概述 1.1 了解关系数据库的局限性 Before diving into NoSQL, it’s essential to understand the challenges posed by traditional Relational Database Management Systems (RDBMS). While RDBMS have been the cornerstone of data management for decades, th…...

C++:this指针

class date { public:void f(int i){} } 以上是我们定义的一个简单的类,这个类里面含有一个简单的成员函数,成员函数看似只有一个参数,实际上是两个参数,除了参数i以外,还有一个指向调用该函数的对象的指针——this指…...

如何在postman使用时间戳

1. 使用 Pre-request Script 动态转换​ 在发送请求前,将日期字符串转为时间戳并存储为环境变量/全局变量。 ​示例代码​ // 将日期字符串(如 "2023-10-01")转为时间戳(毫秒) const dateString "2…...

OCP开闭原则

OCP,software entities(modules,classes,functions,etc.)should be openfor extension, but closed for modification. 软件实体(模块、类和方法等)应该对扩展开发,对修改关闭。 OCP特点 提高可扩展性:新功能通过添…...

计算机网络:什么是Mesh组网以及都有哪些设备支持Mesh组网?

Mesh组网技术详解与实现工具推荐 Mesh组网是一种通过多个节点路由器协同工作,形成覆盖全屋的无线网络的技术。它通过动态路径调整、无缝漫游和自愈能力,解决传统单一路由器覆盖不足的问题,尤其适合大户型、多层住宅或复杂户型环境。以下是Mesh组网的核心原理、实现方式及推…...

STM32f103 标准库 零基础学习之点灯

前提:你已经下好了标准外设库,如果没有可以去找找教程 ST官网上可以下载 目录 前提:你已经下好了标准外设库,如果没有可以去找找教程 ST官网上可以下载 点灯逻辑 1. 定义 GPIO 初始化结构体 2. 开启GPIOA的时钟…...