【redis】哨兵模式

Redis主从模式虽然支持数据备份与读写分离,但存在三大核心缺陷:1. 故障切换依赖人工(主节点宕机需手动提升从节点);2. 监控能力缺失(无法自动检测节点异常);3. 脑裂风险(网络分区可能导致双主数据冲突)。这些缺陷使得系统可用性难以保障,尤其在分布式场景下隐患显著。

为此引入Redis哨兵模式:通过独立部署的哨兵集群(至少3节点)实现:

  • 实时监控:多哨兵协同检测节点健康状态
  • 自动故障转移:主节点宕机时,基于Raft算法选举新主并同步拓扑
  • 防脑裂机制:客观下线判断(需多数哨兵达成共识)避免误判

哨兵模式将故障恢复时间从人工介入的分钟级压缩至秒级,构建了完整的高可用体系。

三大定时监控任务

信息同步任务(10秒/次)

作用:通过INFO命令获取Redis集群的实时拓扑结构,包括主从节点的角色变化、新增从节点发现等。该任务是哨兵感知集群动态的基础。

技术实现

  • 每个哨兵节点每10秒向主节点发送INFO命令,主节点返回包含从节点列表的响应
  • 根据响应更新本地拓扑信息,并与从节点建立连接
  • 发现新从节点时,自动将其纳入监控范围

状态广播任务(2秒/次)

作用:通过Redis的发布订阅机制,实现哨兵节点间的状态同步与协作,具体包括:

  1. 交换节点状态判断:广播当前哨兵对主节点是否下线的判断结果
  2. 发现新哨兵节点:通过解析__sentinel__:hello频道的消息,动态加入新哨兵到集群
  3. 触发Leader选举:当检测到主节点异常时,通过消息触发Raft选举流程

技术实现

  • 哨兵节点既是发布者(发送自身状态),也是订阅者(接收其他哨兵状态)
  • 使用Redis的PUBLISH/SUBSCRIBE机制,避免直接节点间通信的复杂性

心跳检测任务(1秒/次)

作用:通过PING命令实现节点存活检测,触发主观下线(SDOWN)判断流程。

技术实现

  • 每1秒向所有主/从节点及哨兵节点发送PING命令
  • 若节点在down-after-milliseconds(默认30秒)内未响应,标记为主观下线
  • 当主节点被标记为主观下线时,启动客观下线(ODOWN) 投票

下线流程

Redis Sentinel的下线流程分为主观下线客观下线两个核心阶段,最终触发故障转移。

主观下线(SDOWN)

主观下线:Subjectively Down,简称SDOWN。

触发条件:单个Sentinel节点通过心跳检测(PING命令)发现主节点或从节点无响应,且超时时间超过配置的down-after-milliseconds阈值(默认30秒)。

技术细节

  • Sentinel每秒向所有主、从节点发送PING命令,若节点在超时时间内未返回有效响应(如PONG),则标记为主观下线
  • 有效响应包括PONGLOADINGMASTERDOWN;无效响应或无响应则触发判断。

特点

  • 仅代表单个Sentinel的局部判断,可能存在误判(如网络抖动)。
  • 从节点被标记为主观下线后不会触发后续流程,仅主节点需进入客观下线阶段。

客观下线(ODOWN)

客观下线:Objectively Down,简称ODOWN。

触发条件:当足够数量的Sentinel节点(由quorum参数决定)均认为主节点主观下线时,主节点被标记为客观下线,成为故障转移的触发条件。

技术细节

  1. 协商机制:首个标记主节点主观下线的Sentinel会通过SENTINEL is-master-down-by-addr命令向其他Sentinel发起投票请求。
  2. 投票规则:需满足quorum值(如配置为2,则至少2个Sentinel投票确认主节点下线)。
  3. 防误判:多数哨兵达成共识可降低因网络问题导致的误判概率。

关键参数quorum在配置文件中通过sentinel monitor <master> <ip> <port> <quorum>定义,通常建议为哨兵节点数/2 +1

选举领头哨兵(Leader Sentinel)

触发条件:主节点被标记为客观下线后,Sentinel集群需通过Raft算法选举一个领头哨兵来执行故障转移。

选举规则

  1. 候选资格:仅发起客观下线投票的Sentinel可成为候选者。
  2. 投票机制:每个Sentinel仅能投一票(可投给自己或他人)。候选者需同时满足:获得半数以上Sentinel的投票和得票数≥quorum值。
  3. 超时重试:若选举失败,等待随机时间后重新发起投票。

is-master-down-by-addr命令说明:

SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>
  • ip & port:目标主节点地址。
  • current_epoch:当前配置纪元(用于防止旧消息干扰)。
  • runid:
    • runid=*:仅询问其他哨兵是否同意主节点下线(用于客观下线判定)。
    • runid=哨兵自身ID:请求其他哨兵投票支持自己成为故障转移的领导者。

故障转移流程

执行步骤

  1. 筛选从节点:剔除网络连接不稳定的从节点(如断连次数超过down-after-milliseconds*10阈值)。
  2. 打分规则(优先级排序):
  • 第一轮:选择slave-priority配置值最小的从节点(优先级最高)。
  • 第二轮:选择复制偏移量(slave_repl_offset)最大的从节点(数据最新)。
  • 第三轮:选择运行ID(runid)最小的从节点(字典序最小)。
  1. 主从切换
  • 领头Sentinel向新主节点发送slaveof no one命令。
  • 更新其他从节点指向新主节点,并通知客户端新拓扑信息。

主从切换成功后,sentinel会在+switch-master频道发发送主节点切换消息:

$ redis-cli -p 16381 subscribe +switch-master
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "+switch-master"
3) (integer) 1
1) "message"
2) "+switch-master"
3) "mymaster 127.0.0.1 6381 127.0.0.1 6382"

哨兵模式实战部署

Redis节点规划如下:

  • Master: 127.0.0.1:6380
  • Slave1: 127.0.0.1:6381(直连Master)
  • Slave2: 127.0.0.1:6382(直连Master)
  • Sentinel1:127.0.0.1:16380
  • Sentinel2:127.0.0.1:16381
  • Sentinel3:127.0.0.1:16382

在/test/目录分别新建/test/6380、/test/6381、/test/6382三个目录,用来存放redis的数据文件。然后在/test/目录分别新建/test/16380、/test/16381、/test/16382三个目录,用来存放sentinel的数据文件,这三个目录下都新建redis.conf文件,内容如下:

# /test/16380/redis.conf
port 16380
sentinel monitor mymaster 127.0.0.1 6380 2# /test/16381/redis.conf
port 16381
sentinel monitor mymaster 127.0.0.1 6380 2# /test/16382/redis.conf
port 16382
sentinel monitor mymaster 127.0.0.1 6380 2

三个sentinel数据目录下的文件内容都差不多,只有端口不一样,其中mymaster可以为任意的名字,一个sentinel可以对多个集群中的master节点进行监控,最后一个数字2的含义为3个节点中有2个节点(2票)判定master挂了就会开始自动故障转移。

先启动Master和2个Slave:

$ redis-server --dir /test/6380 --port 6380$ redis-server --dir /test/6381 --port 6381 --replicaof 127.0.0.1 6380$ redis-server --dir /test/6382 --port 6382 --replicaof 127.0.0.1 6380

然后启动三台sentinel(也可以使用单独的redis-sentinel命令):

$ redis-server /test/16380/redis.conf --sentinel$ redis-server /test/16381/redis.conf --sentinel$ redis-server /test/16382/redis.conf --sentinel

从Sentinel1的日志中能发现,它能根据Master节点找到2个Slave,以及其他两个Sentinel:

4922:X 16 Apr 2025 16:31:46.120 # Sentinel ID is ddb55a52514d296a3dca1123cfceaa309c134267
4922:X 16 Apr 2025 16:31:46.120 # +monitor master mymaster 127.0.0.1 6380 quorum 2
4922:X 16 Apr 2025 16:31:46.121 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
4922:X 16 Apr 2025 16:31:46.124 * +slave slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
4922:X 16 Apr 2025 16:31:51.117 * +sentinel sentinel 9cc17be7b7e700d2800751113c5b0dad0944650f 127.0.0.1 16381 @ mymaster 127.0.0.1 6380
4922:X 16 Apr 2025 16:31:53.329 * +sentinel sentinel 950c560895d65451db8b65ebc0a418feef21ba82 127.0.0.1 16382 @ mymaster 127.0.0.1 6380

Sentinel可以通过向Master发送info命令来找到其他Slave:

$ redis-cli -p 6380 info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=5399,lag=0
slave1:ip=127.0.0.1,port=6382,state=online,offset=5399,lag=0
master_failover_state:no-failover
master_replid:1eeb77e6f1d2ca889541314746796ccb6efa4404
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:5399
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:5399

Sentinel是怎么找到其他Sentinel的呢,原来他们都在主节点和所有的从节点上订阅了同一个频道,并将自己的信息发送到频道中,像一个聊天窗口一样,可以使用下面的命令来查看他们的聊天内容:

$ redis-cli -p 6380 subscribe __sentinel__:hello
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "__sentinel__:hello"
3) (integer) 1
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1,16381,9cc17be7b7e700d2800751113c5b0dad0944650f,0,mymaster,127.0.0.1,6380,0"
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1,16382,950c560895d65451db8b65ebc0a418feef21ba82,0,mymaster,127.0.0.1,6380,0"
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1,16380,ddb55a52514d296a3dca1123cfceaa309c134267,0,mymaster,127.0.0.1,6380,0"
...

现在关闭Master节点,过了大概30s(由参数down-after-milliseconds决定),6381就称为了master节点,可以从Sentinel的日志中查看自动故障转移的大概过程。

Sentinel1:

4922:X 16 Apr 2025 16:34:02.955 # +sdown master mymaster 127.0.0.1 6380
4922:X 16 Apr 2025 16:34:03.043 # +new-epoch 1
4922:X 16 Apr 2025 16:34:03.051 # +vote-for-leader 950c560895d65451db8b65ebc0a418feef21ba82 1
4922:X 16 Apr 2025 16:34:03.680 # +config-update-from sentinel 950c560895d65451db8b65ebc0a418feef21ba82 127.0.0.1 16382 @ mymaster 127.0.0.1 6380
4922:X 16 Apr 2025 16:34:03.680 # +switch-master mymaster 127.0.0.1 6380 127.0.0.1 6381
4922:X 16 Apr 2025 16:34:03.680 * +slave slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6381
4922:X 16 Apr 2025 16:34:03.681 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
4922:X 16 Apr 2025 16:34:33.756 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381

Sentinel2:

4927:X 16 Apr 2025 16:34:02.996 # +sdown master mymaster 127.0.0.1 6380
4927:X 16 Apr 2025 16:34:03.042 # +new-epoch 1
4927:X 16 Apr 2025 16:34:03.050 # +vote-for-leader 950c560895d65451db8b65ebc0a418feef21ba82 1
4927:X 16 Apr 2025 16:34:03.068 # +odown master mymaster 127.0.0.1 6380 #quorum 3/2
4927:X 16 Apr 2025 16:34:03.068 # Next failover delay: I will not start a failover before Wed Apr 16 16:40:03 2025
4927:X 16 Apr 2025 16:34:03.680 # +config-update-from sentinel 950c560895d65451db8b65ebc0a418feef21ba82 127.0.0.1 16382 @ mymaster 127.0.0.1 6380
4927:X 16 Apr 2025 16:34:03.680 # +switch-master mymaster 127.0.0.1 6380 127.0.0.1 6381
4927:X 16 Apr 2025 16:34:03.680 * +slave slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6381
4927:X 16 Apr 2025 16:34:03.680 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
4927:X 16 Apr 2025 16:34:33.739 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381

Sentinel3:

4932:X 16 Apr 2025 16:34:02.959 # +sdown master mymaster 127.0.0.1 6380
4932:X 16 Apr 2025 16:34:03.022 # +odown master mymaster 127.0.0.1 6380 #quorum 2/2
4932:X 16 Apr 2025 16:34:03.022 # +new-epoch 1
4932:X 16 Apr 2025 16:34:03.022 # +try-failover master mymaster 127.0.0.1 6380
4932:X 16 Apr 2025 16:34:03.037 # +vote-for-leader 950c560895d65451db8b65ebc0a418feef21ba82 1
4932:X 16 Apr 2025 16:34:03.050 # 9cc17be7b7e700d2800751113c5b0dad0944650f voted for 950c560895d65451db8b65ebc0a418feef21ba82 1
4932:X 16 Apr 2025 16:34:03.052 # ddb55a52514d296a3dca1123cfceaa309c134267 voted for 950c560895d65451db8b65ebc0a418feef21ba82 1
4932:X 16 Apr 2025 16:34:03.104 # +elected-leader master mymaster 127.0.0.1 6380
4932:X 16 Apr 2025 16:34:03.105 # +failover-state-select-slave master mymaster 127.0.0.1 6380
4932:X 16 Apr 2025 16:34:03.158 # +selected-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
4932:X 16 Apr 2025 16:34:03.158 * +failover-state-send-slaveof-noone slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
4932:X 16 Apr 2025 16:34:03.216 * +failover-state-wait-promotion slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
4932:X 16 Apr 2025 16:34:03.625 # +promoted-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
4932:X 16 Apr 2025 16:34:03.625 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6380
4932:X 16 Apr 2025 16:34:03.680 * +slave-reconf-sent slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
4932:X 16 Apr 2025 16:34:04.173 # -odown master mymaster 127.0.0.1 6380
4932:X 16 Apr 2025 16:34:04.686 * +slave-reconf-inprog slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
4932:X 16 Apr 2025 16:34:04.686 * +slave-reconf-done slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
4932:X 16 Apr 2025 16:34:04.738 # +failover-end master mymaster 127.0.0.1 6380
4932:X 16 Apr 2025 16:34:04.738 # +switch-master mymaster 127.0.0.1 6380 127.0.0.1 6381
4932:X 16 Apr 2025 16:34:04.738 * +slave slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6381
4932:X 16 Apr 2025 16:34:04.738 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
4932:X 16 Apr 2025 16:34:34.752 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381

再去看一下sentinel的数据目录的redis.conf文件的内容(sentinel会自动更新配置文件):

$ cat /test/16380/redis.conf
port 16380
sentinel monitor mymaster 127.0.0.1 6381 2
# Generated by CONFIG REWRITE
protected-mode no
user default on nopass ~* &* +@all
dir "/test"
sentinel myid ddb55a52514d296a3dca1123cfceaa309c134267
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
sentinel current-epoch 1
sentinel known-replica mymaster 127.0.0.1 6380
sentinel known-replica mymaster 127.0.0.1 6382
sentinel known-sentinel mymaster 127.0.0.1 16381 9cc17be7b7e700d2800751113c5b0dad0944650f
sentinel known-sentinel mymaster 127.0.0.1 16382 950c560895d65451db8b65ebc0a418feef21ba82

最后再启动原来关闭的Master节点,它会被sentinel监控到,然后成为6381的从节点。

关键配置参数说明

# 定义哨兵监控的主节点信息。
# quorum:触发主节点客观下线(ODOWN)所需的最小哨兵投票数。
# quorum通常设置为哨兵节点数的一半加一(如3哨兵时设为2),避免误判。
sentinel monitor <master-name> <ip> <port> <quorum># 定义节点无响应多久后被标记为主观下线(SDOWN)
sentinel down-after-milliseconds <master-name> <ms># 故障转移后,允许同时从新主节点同步数据的从节点数量。 
sentinel parallel-syncs <master-name> <num># 定义故障转移各阶段的最大超时时间
sentinel failover-timeout <master-name> <ms># 设置连接主节点和从节点的密码
sentinel auth-pass <master-name> <password># 在NAT或Docker环境中,指定哨兵对外通信的IP和端口
sentinel announce-ip <ip>
sentinel announce-port <port> # 显式声明从节点地址,避免自动发现延迟
sentinel known-replica <master-name> <ip> <port># 定义故障事件触发的报警脚本路径
sentinel notification-script <master-name> <script-path>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/902576.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spark-Streaming

找出所有有效数据&#xff0c;要求电话号码为11位&#xff0c;但只要列中没有空值就算有效数据。 按地址分类&#xff0c;输出条数最多的前20个地址及其数据。 代码讲解&#xff1a; 导包和声明对象&#xff0c;设置Spark配置对象和SparkContext对象。 使用Spark SQL语言进行数…

Sentinel源码—9.限流算法的实现对比一

大纲 1.漏桶算法的实现对比 (1)普通思路的漏桶算法实现 (2)节省线程的漏桶算法实现 (3)Sentinel中的漏桶算法实现 (4)Sentinel中的漏桶算法与普通漏桶算法的区别 (5)Sentinel中的漏桶算法存在的问题 2.令牌桶算法的实现对比 (1)普通思路的令牌桶算法实现 (2)节省线程的…

Redis 详解:安装、数据类型、事务、配置、持久化、订阅/发布、主从复制、哨兵机制、缓存

目录 Redis 安装与数据类型 安装指南 Windows Linux 性能测试 基本知识 数据类型 String List&#xff08;双向列表&#xff09; Set&#xff08;集合&#xff09; Hash&#xff08;哈希&#xff09; Zset&#xff08;有序集合&#xff09; 高级功能 地理位置&am…

Docker配置带证书的远程访问监听

一、生成证书和密钥 1、准备证书目录和生成CA证书 # 创建证书目录 mkdir -p /etc/docker/tls cd /etc/docker/tls # 生成CA密钥和证书 openssl req -x509 -newkey rsa:4096 -keyout ca-key.pem \ -out ca-cert.pem -days 365 -nodes -subj "/CNDocker CA" 2、为…

MCP接入方式介绍

上一篇文章&#xff0c;我们介绍了MCP是什么以及MCP的使用。 MCP是什么&#xff0c;MCP的使用 接下来&#xff0c;我们来详细介绍一下MCP的接入 先看官网的架构图 上图的MCP 服务 A、MCP 服务 B、MCP 服务 C是可以运行在你的本地计算机&#xff08;本地服务器方式&#xff…

关于Agent的简单构建和分享

前言&#xff1a;Agent 具备自主性、环境感知能力和决策执行能力&#xff0c;能够根据环境的变化自动调整行为&#xff0c;以实现特定的目标。 一、Agent 的原理 Agent(智能体)被提出时&#xff0c;具有四大能力 感知、分析、决策和执行。是一种能够在特定环境中自主行动、感…

Gitlab runner 安装和注册

Gitlab Runner GitLab Runner是一个用于运行GitLab CI/CD流水线作业的软件包&#xff0c;由GitLab官方开发&#xff0c;完全开源。你可以在很多主流的系统环境或平台上安装它&#xff0c;如Linux、macOS、Windows和Kubernetes。如果你熟悉Jenkins 的话&#xff0c;你可以把它…

精益数据分析(18/126):权衡数据运用,精准把握创业方向

精益数据分析&#xff08;18/126&#xff09;&#xff1a;权衡数据运用&#xff0c;精准把握创业方向 大家好&#xff01;一直以来&#xff0c;我都希望能和大家在创业与数据分析的领域共同探索、共同进步。今天&#xff0c;我们继续深入研读《精益数据分析》&#xff0c;探讨…

Git技术详解:从核心原理到实际应用

Git技术详解&#xff1a;从核心原理到实际应用 一、Git的本质与核心价值 Git是由Linux之父Linus Torvalds在2005年开发的分布式版本控制系统&#xff0c;其核心功能是通过记录文件变更历史&#xff0c;帮助开发者实现以下目标&#xff1a; 版本回溯&#xff1a;随时恢复到项…

Java从入门到“放弃”(精通)之旅——String类⑩

Java从入门到“放弃”&#xff08;精通&#xff09;之旅&#x1f680;——String类⑩ 前言 在Java编程中&#xff0c;String类是最常用也是最重要的类之一。无论是日常开发还是面试&#xff0c;对String类的深入理解都是必不可少的。 1. String类的重要性 在C语言中&#xf…

抓取淘宝数据RPA--影刀

最近用了一下RPA软件&#xff0c;挑了影刀&#xff0c;发现很无脑也很简单&#xff0c;其语法大概是JAVA和PYTHON的混合体&#xff0c;如果懂爬虫的话&#xff0c;学这个软件就快的很&#xff0c;看了一下官方的教程&#xff0c;对于有基础的人来说很有点枯燥&#xff0c;但又不…

docker部署seafile修改默认端口并安装配置onlyoffice实现在线编辑

背景 有很多场景会用到类似seafile功能的需求&#xff0c;比如&#xff1a; 在内网中传输和共享文件个人部署私人网盘文档协同在线编辑写笔记… 这些功能seafile均有实现&#xff0c;并且社区版提供的功能基本可以满足个人或者小型团队的日常需求 问题 由于主机的80和443端…

计算机视觉cv2入门之视频处理

在我们进行计算机视觉任务时&#xff0c;经常会对视频中的图像进行操作&#xff0c;这里我来给大家分享一下&#xff0c;cv2对视频文件的操作方法。这里我们主要介绍cv2.VideoCapture函数的基本使用方法。 cv2.VideoCapture函数 当我们在使用cv2.VideoCapture函数时&#xff…

Linux之彻底掌握防火墙-----安全管理详解

—— 小 峰 编 程 目录&#xff1a; 一、防火墙作用 二、防火墙分类 1、逻辑上划分&#xff1a;大体分为 主机防火墙 和 网络防火墙 2、物理上划分&#xff1a; 硬件防火墙 和 软件防火墙 三、硬件防火墙 四、软件防火墙 五、iptables 1、iptables的介绍 2、netfilter/…

python项目实战-后端个人博客系统

本文分享一个基于 Flask 框架开发的个人博客系统后端项目&#xff0c;涵盖用户注册登录、文章发布、分类管理、评论功能等核心模块。适合初学者学习和中小型博客系统开发。 一、项目结构 blog │ app.py │ forms.py │ models.py │ ├───instance │ blog.d…

Unity 接入阿里的全模态大模型Qwen2.5-Omni

1 参考 根据B站up主阴沉的怪咖 开源的项目的基础上修改接入 AI二次元老婆开源项目地址(unity-AI-Chat-Toolkit): Github地址&#xff1a;https://github.com/zhangliwei7758/unity-AI-Chat-Toolkit Gitee地址&#xff1a;https://gitee.com/DammonSpace/unity-ai-chat-too…

第十五届蓝桥杯 2024 C/C++组 合法密码

目录 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路&#xff1a; substr函数&#xff1a; 思路详解&#xff1a; 代码&#xff1a; 代码详解; 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; P10906 [蓝桥杯 2024 国 B] 合法密码 -…

NoSQL 简单讲解

目录 1. NoSQL 的背景与意义 1.1 数据库的演变 1.2 NoSQL 的兴起 2. NoSQL 数据库的分类 2.1 键值存储&#xff08;Key-Value Stores&#xff09; 2.2 文档数据库&#xff08;Document Stores&#xff09; 2.3 列族存储&#xff08;Column-Family Stores&#xff09; 2.…

122.在 Vue3 中使用 OpenLayers 实现图层层级控制(zIndex)显示与设置详解

📅 作者:彭麒 📫 邮箱:1062470959@qq.com 📌 声明:本文源码归吉檀迦俐所有,欢迎学习借鉴,如用于商业项目请注明出处 🙌 🔧 技术栈:Vue 3 + Composition API + OpenLayers 6+ + Element Plus + Tailwind CSS 🧠 一、什么是 zIndex(图层层级)? 在地图开发中…

车载测试用例开发-如何平衡用例覆盖度和测试效率的方法论

1 摘要 在进行车载测试用例编写时&#xff0c;会遇到多个条件导致用例排列组合爆炸的情况&#xff0c;但是为了产品测试质量&#xff0c;我们又不得不保证用例设计的需求覆盖度&#xff0c;这样又会使得测试周期非常长。我们如何平衡效率和测试质量&#xff1f;本文进行了一些…