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

Redis设计与实现-哨兵

哨兵模式

  • 1、启动并初始化sentinel
    • 1.1 初始化服务器
    • 1.2 使用Sentinel代码
    • 1.3 初始化sentinel状态
    • 1.4 初始化sentinel状态的master属性
    • 1.5 创建连向主服务器的网络连接
  • 2、获取主服务器信息
  • 3、获取从服务器的信息
  • 4、向主从服务器发送信息
  • 5、接受主从服务器的频道信息
  • 6、检测主观下线状态
  • 7、检查客观下线状态
  • 8、选择领头的sentinel
  • 9、故障转移
    • 9.1 选择新主服务器
    • 9.2 修改从服务器复制目标
    • 9.3 将旧的主服务器转换为从服务器

如有侵权,请联系~
如有错误,也欢迎批评指正~
本篇文章大部分是来自学习《Redis设计与实现》的笔记

哨兵(Sentinel)是Redis的高可用解决方案:由一个或者多个哨兵实例组成的哨兵系统,可以监视任意多个主服务器以及这些主服务器所属下的所有从服务器,并且在被监视的主服务器下线时自动的将从某个服务器升级为新的主服务器,然后将新的主服务器替换已经下线的主服务器继续处理命令请求。

1、启动并初始化sentinel

启动一个Sentinel可以使用如下命令:

redis-sentinel /path/your/sentinel.conf
redis-server /path/your/sentinel.conf --sentinel

启动一个sentinel服务器,需要执行如下步骤:

  1. 初始化服务器
  2. 将普通的Redis服务器使用的代码代替为Sentinel专用代码
  3. 初始化Sentinel状态
  4. 根据给定的配置文件,初始化Sentinel的监视主服务器列表
  5. 创建与主服务器的网络连接

1.1 初始化服务器

因为Sentinel哨兵实例本质上就是一个运行在特殊模式下的Redis服务器,所以这一步初始化服务器就是初始化一个redis实例,参考Redis设计与实现-底层实现。
但是毕竟两者工作的方式不一样,所以初始化过程还是有所不一样,例如哨兵初始化是不需要RDB文件或者AOF文件还原数据库。

1.2 使用Sentinel代码

将普通redis使用的代码替换为sentinel哨兵使用的代码。例如,redis的服务端端口号为6379,哨兵使用26379.

define REDIS_SERVERPORT 6379
define REDIS_SENTINEL_PORT 26379

哨兵的命令表也和redis服务器的不同,哨兵对客户端提供的命令PING、SENTINEL、INFO、SUBSCRIBE、UNSUBSCRIBE、PSUBSCRIBE和PUNSUBSCRIBE,不对外提供set get等redis的基础命令。

1.3 初始化sentinel状态

接下来会初始化哨兵的状态sentinelState结构,SentinelState 是 Redis Sentinel 内部用来表示全局状态的数据结构。它包含了所有监控的主节点、从节点、哨兵实例以及配置信息。

typedef struct sentinelState {uint64_t current_epoch;       // 当前的纪元(epoch),用于故障转移选举dict *masters;                // 主节点字典,key 为被监控主节点名称,value 为 sentinelRedisInstanceint tilt;                     // 是否处于倾斜模式(Tilt Mode)int running_scripts;          // 当前正在运行的脚本数量mstime_t tilt_start_time;     // 倾斜模式开始的时间mstime_t previous_time;       // 上一次时间戳,用于检测时间跳跃list *scripts_queue;          // 脚本队列,用于执行用户定义的脚本
} sentinelState;

1.4 初始化sentinel状态的master属性

sentinel状态会保存所有监控的主服务器的信息master,而这个master的key就是主服务器的名字,value就是sentinelRedisInstance。这一步就是初始化master字典。为什么只保存主服务器信息?因为从服务器是动态的,sentinel会通过主服务器进行获取。

typedef struct sentinelRedisInstance {int flags;                    // 实例标志位(如主节点、从节点、哨兵等)char *name;                   // 实例名称(仅主节点有名称)redisAsyncContext *cc;        // 与该实例的命令连接redisAsyncContext *pc;        // 与该实例的发布/订阅连接mstime_t last_pub_time;       // 上一次发送 PUBLISH 消息的时间mstime_t last_hello_time;     // 上一次收到 HELLO 消息的时间mstime_t last_master_down_time; // 上一次检测到主节点下线的时间mstime_t down_after_period;   // 判定实例下线的时间阈值mstime_t info_refresh;        // INFO 命令刷新的时间间隔dict *renamed_commands;       // 重命名的 Redis 命令映射int parallel_syncs;           // 故障转移后允许同时同步的从节点数量int quorum;                   // 判定主节点不可用所需的最小哨兵数量list *sentinels;              // 监控该主节点的所有哨兵实例list *slaves;                 // 主节点的所有从节点struct sentinelRedisInstance *master; // 如果是从节点,指向其主节点...
} sentinelRedisInstance;

1.5 创建连向主服务器的网络连接

哨兵sentinel会向主服务器建立网络连接,针对于一个主服务器需要建立两个网络连接:

  • 用于命令回复的网络连接,主要用来向主服务器发送命令请求,接受命令回复
  • 用于订阅功能的网络连接,用来订阅主服务器的_sentinel_:hello频道

2、获取主服务器信息

sentinel哨兵会每10秒向监控的主服务器发送INFO命令,并通过主服务器返回的INFO命令回复进行分析更新相应主服务器的sentinelRedisInstance。INFO命令主服务器返回的结果如下:

# server部分
redis_version:6.2.6                  # Redis 版本号
redis_mode:standalone                # Redis 模式 (standalone 或 cluster)
os:Linux 5.4.0-42-generic x86_64     # 操作系统信息
arch_bits:64                         # 架构位数 (3264)
process_id:12345                     # Redis 进程 ID
run_id:abcdef1234567890abcdef1234567890abcdef1234567890abcdef12 # 运行 ID
tcp_port:6379                        # Redis 服务端口
uptime_in_seconds:123456             # Redis 运行时间(秒)
uptime_in_days:1                     # Redis 运行时间(天)
hz:10                                # Redis 内部定时器频率# client部分
connected_clients:10                 # 当前连接的客户端数量
client_recent_max_input_buffer:2     # 最大输入缓冲区大小
client_recent_max_output_buffer:0    # 最大输出缓冲区大小
blocked_clients:0                    # 被阻塞的客户端数量# replication部分
role:master                          # 角色:主节点
connected_slaves:2                   # 已连接的从节点数量
slave0:ip=192.168.1.2,port=6379,state=online,offset=12345678,lag=0
slave1:ip=192.168.1.3,port=6379,state=online,offset=12345678,lag=1
master_replid:abcdef1234567890abcdef1234567890abcdef1234567890abcdef12
master_replid2:00000000000000000000000000000000000000000000000000000000
master_repl_offset:12345678          # 主节点的复制偏移量
second_repl_offset:-1                # 第二个复制 ID 的偏移量
repl_backlog_active:1                # 是否启用了复制积压缓冲区
repl_backlog_size:1048576            # 复制积压缓冲区大小
repl_backlog_first_byte_offset:12345 # 积压缓冲区的第一个字节偏移量
repl_backlog_histlen:12345           # 积压缓冲区的历史长度....

通过分析上述命令回复会更新对应主服务器的sentinelRedisInstance,这个命令回复也会返回从服务器的信息。如果有新增的从服务器就会为从服务器创建新的sentinelRedisInstance,添加到主服务的sentinelRedisInstance.slaves属性中。

3、获取从服务器的信息

当有新的从服务器出现的时候,sentinel会在该主服务下的slaves中添加一个sentinelRedisInstance实例,并且和从服务器创建命令连接和订阅连接。
命令创建完成之后,sentinel默认10秒通过命令连接向从服务器发一次info命令,并且返回:

# Replication
role:slave                   # 角色为从节点
master_host:127.0.0.1        # 主节点IP
master_port:6379             # 主节点端口
master_link_status:up        # 与主节点的连接状态(up/down)
master_last_io_seconds_ago:1 # 上次与主节点通信的秒数(反映复制延迟)
master_sync_in_progress:0    # 是否正在全量同步(0=否,1=是)
slave_repl_offset:123456     # 当前复制偏移量(用于评估数据同步进度)
slave_priority:100           # 从节点优先级(故障转移时影响选举)
slave_read_only:1            # 是否只读模式(默认1# Server
redis_version:6.2.6         # Redis版本
os:Linux 5.4.0-80-generic   # 运行的操作系统
uptime_in_seconds:86400     # 运行时间(秒)
# Clients
connected_clients:3         # 当前客户端连接数

根据从服务器返回的数据,更新sentinelRedisInstance实例。

4、向主从服务器发送信息

sentinel每两秒就会通过订阅连接向主从服务器发送信息。当 Sentinel 在 sentinel:hello 频道上发布消息时,消息内容通常包含以下信息:

publish __sentinel__:hello <sentinel-ip>,<sentinel-port>,<runid>,<current_epoch>,<master-name>,<master-ip>,<master-port>,<master-config-epoch>
  • sentinel-ip 和 sentinel-port:当前 Sentinel 的地址。
  • runid:当前 Sentinel 的运行 ID。
  • current_epoch:当前的配置纪元(用于协调故障转移)。
  • master-name:被监控的主节点名称。
  • master-ip 和 master-port:主节点的地址。
  • master-config-epoch:主节点的配置纪元。

5、接受主从服务器的频道信息

有关频道的订阅关系,针对于一个主从服务Redis集群会分配单独的订阅频道,即不同redis主服务器之间的频道是相互独立的。针对于同一个频道,不仅所有的哨兵和redis主从服务器都订阅这个频道,而且他们也都可以向这个频道发布消息。
所以通过这个频道 redis服务器可以向监听自己的所有sentinel发送消息。
在这里插入图片描述
通过上图可以知道,一个哨兵sentinel发送消息之后除了redis服务器可以接收到数据之外,其他监听这个redis主服务的sentinel也会收到消息。
一个sentinel发送消息之后,sentinel的处理:

  • 如果发现接收到的sentinel runId和自己的一样,说明是自己发送的,则丢弃
  • 如果发现不一样,则根据发送的消息解析出sentinel和主服务器的信息。通过主服务器的信息在自己的sentinelServer的master字典中找到这个主服务器的sentinelRedisInstance实例,然后查看该实例下sentinels【监听这个主服务器的其他sentinel】是否存在。如果存在则更新数据;否则创建实例,并且与这个sentinel彼此创建命令连接。

sentinel和redis服务器的命令连接和订阅关系。【本图没有画各个sentinel与redis服务器的命令连接】(sentinel之间只有命令连接,没有订阅)
在这里插入图片描述

6、检测主观下线状态

默认情况下,sentinel会每秒都会向与其建立命令连接的所有实例【主服务器、从服务器以及与其相连的sentinel】发送ping命令,并根据实例返回的命令回复是否有限【有效回复+PONG、- LOADING、- MASTERDOWN】进行判断是否在线。

sentinel会根据配置文件中down-after-milliseconds参数判断该实例是否为主观下线。即一个实例连续down-after-milliseconds毫秒内一直无效回复,则标记为主观下线,在该实例的sentinelRedisInstance的flags属性设置为sri_s_down标识。

注意每个sentinel配置文件中的down-after-milliseconds值可能不同,有的可能为1000,有的可能为5000。所以,一个实例下线并不一定所有的sentinel都同时认为下线。

当一个 Sentinel 实例判断另一个 Sentinel 实例为主观下线后,它会执行以下操作:

  • 记录主观下线状态:当前 Sentinel 会将目标 Sentinel 标记为 主观下线,并记录其状态。
    这一状态仅存在于当前 Sentinel 的视角中,并不会立即影响系统的整体行为。
  • 通知其他 Sentinel 实例:通知其他 Sentinel 实例自己对目标 Sentinel 的判断结果。其他 Sentinel 实例可以接收到这些消息,但它们会根据自己的健康检查结果独立判断目标 Sentinel 是否也处于主观下线状态。
  • 不触发客观下线

7、检查客观下线状态

当sentinel判断一个主服务器为主观下线之后,为了进一步判断是否真的下线,会问其他sentinel哨兵是否下线。当超过quorum个sentinel认为该主服务器下线,则就会将这个redis主服务器标记为客观下线。【从服务器不需要进行判断客观下线,影响比较小】

SENTINEL IS-MASTER-DOWN-BY-ADDR 是 Redis Sentinel 提供的一个命令,用于检查某个主节点是否被标记为下线(主观下线或客观下线),并参与领导者选举的协商过程。sentinel通过命令连接进行发送的,不是通过hello频道发送的。

SENTINEL IS-MASTER-DOWN-BY-ADDR命令:

SENTINEL IS-MASTER-DOWN-BY-ADDR <master-ip> <master-port> <current-epoch> <runid>

参数说明:

  • master-ip和 master-port:指定要检查的主节点的 IP 地址和端口号。
  • current-epoch:当前的配置纪元(configuration epoch)。配置纪元是一个递增的数字,用于协调多个 Sentinel 实例之间的状态变更和领导者选举。
  • runid:如果该参数为 *,表示当前 Sentinel 只是询问其他 Sentinel 是否认为主节点已下线。
    如果该参数为具体的运行 ID(如当前 Sentinel 的 runid),表示当前 Sentinel 希望竞选成为领导者。

目标 Sentinel 返回包含三个参数的响应:

  • down_state:
    • 1 表示目标 Sentinel 认为主节点已下线;
    • 0 表示认为主节点在线。
  • leader_runid:
    • 若为 *,表示回复仅用于主节点状态检测;
    • 若为具体 runid,表示目标 Sentinel 同意该 runid 对应的 Sentinel 成为故障转移的领导者。
  • leader_epoch: 目标 Sentinel 的局部领头配置纪元(仅当 leader_runid 不为 * 时有效)

sentinel会根据该命令的回复判断,是否超过quorum个sentinel回复了一下线。客观下线则会将该redis主服务器实例的sentinelRedisInstance的flags属性设置为sri_o_down标识。

同样,不同的sentinel可能配置文件不一样,从而会出现quorum大小不一样,可能出现有的sentinel认为主服务器已经下线,有的认为没有客观下线。

8、选择领头的sentinel

只要判断主机已经客观下线之后,监听这个主机的各个sentinel进行协商,选择一个领头的sentinel,由这个领头的sentinel负责故障转移。

  • 源哨兵期望成为领头的sentinel,所以源sentinel向目标sentinel发送sentinel is-master-down-by-addr命令,并且runid为源sentinel的runid。
  • 目标sentinel会根据先到先得,如果没有在这个记元投递给其他sentinel,就会投递给这个sentinel,回复的leader_runid和leader_epoch分别为源sentinel的runid和目标sentinel的epoch。否则就会拒绝
  • 源sentinel接收到命令回复之后,会判断epoch和自己的epoch是否一样以及回复的runid是否等于自己的epoch。
  • 如果某个sentinel超过半数以上,则会成为领头sentinel执行故障转移。如果都没有满足这一条件的,则过一段时间再进行选举。每次选举epoch都会加1,无论是否成功。

9、故障转移

在选择了领头sentinel之后,由领头sentinel负责故障转移。进行故障转移主要步骤为:从那些可用的从服务器中选择主服务器、将其他从服务器复制新的主服务器、将已经下线的主服务器也作为新主服务器的从服务器。

9.1 选择新主服务器

领头sentinel从所有从服务器中选择状态良好、数据完整的从服务器作为新主服务器,并向这个从服务器发送slave no one命令,将这服务器设置为主服务器。选择主服务的步骤大致如下:

  1. 从所有的从服务器中删除处于下线的服务器
  2. 从所有的从服务器中删除5秒内没有回复info命令的服务器
  3. 然后从剩余的从服务器根据【 优先级 > 复制偏移量大 > 运行runId最小】的原则选择作为从服务器作为主服务器
    在这里插入图片描述
    在这里插入图片描述

9.2 修改从服务器复制目标

将其他从服务器复制新的主服务器,领头sentinel会向其他的从服务器发送slave <新主服务器ip> <新主服务器port>。
在这里插入图片描述

9.3 将旧的主服务器转换为从服务器

接下来就是将旧的主服务器转换为从服务器,当旧的主服务器重新启动之后,sentinel会向它发送slave <新主服务器ip> <新主服务器port>命令。
在这里插入图片描述

相关文章:

Redis设计与实现-哨兵

哨兵模式 1、启动并初始化sentinel1.1 初始化服务器1.2 使用Sentinel代码1.3 初始化sentinel状态1.4 初始化sentinel状态的master属性1.5 创建连向主服务器的网络连接 2、获取主服务器信息3、获取从服务器的信息4、向主从服务器发送信息5、接受主从服务器的频道信息6、检测主观…...

vscode 打开工程 看不到文件目录

vscode 打开工程 看不到文件目录 View->Explorer 快捷键&#xff1a;CtrlShiftE...

[c++项目]基于微服务的聊天室服务端测试

项目概述 本测试报告针对基于C实现的微服务架构聊天室服务端进行全面测试。系统主要包含以下微服务&#xff1a; 用户认证服务&#xff08;Auth Service&#xff09;消息处理服务&#xff08;Message Service&#xff09;在线状态服务&#xff08;Presence Service&#xff0…...

Java面试黄金宝典16

1. 各种排序算法的时间复杂度和空间复杂度 冒泡排序 定义&#xff1a; 冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换&#xff0c;…...

pytorch中dataloader自定义数据集

前言 在深度学习中我们需要使用自己的数据集做训练&#xff0c;因此需要将自定义的数据和标签加载到pytorch里面的dataloader里&#xff0c;也就是自实现一个dataloader。 数据集处理 以花卉识别项目为例&#xff0c;我们分别做出图片的训练集和测试集&#xff0c;训练集的标…...

LabVIEW 燃气轮机气路故障诊断

在船用燃气轮机气路故障诊断领域&#xff0c;LabVIEW 软件以其独特的功能和优势&#xff0c;成为构建高效、精准诊断系统的关键技术支撑。它全面覆盖硬件在环仿真平台的各个环节&#xff0c;从硬件连接、数据交互到系统功能实现&#xff0c;都发挥着不可替代的作用&#xff0c;…...

[项目]基于FreeRTOS的STM32四轴飞行器: 十六.激光测距定高功能

基于FreeRTOS的STM32四轴飞行器: 十六.激光测距定高功能 一.芯片介绍二.配置CubeMX三.激光测距芯片驱动编写四.定高PID的计算五.定高PID作用到电机上 一.芯片介绍 激光测高芯片在飞控板下侧&#xff1a; 原理图如下&#xff1a; 型号为&#xff1a;VL53LX1&#xff0c;为国产…...

HTML跑酷

先看效果 再上代码 <!DOCTYPE html> <html> <head><title>火柴人跑酷</title><style>body {margin: 0;overflow: hidden;background: #87CEEB;}#gameCanvas {background: linear-gradient(to bottom, #87CEEB 0%, #87CEEB 50%, #228B22 …...

C++Primer学习(14.1 基本概念)

当运算符作用于类类型的运算对象时&#xff0c;可以通过运算符重载重新定义该运算符的含义。明智地使用运算符重载能令我们的程序更易于编写和阅读。举个例子&#xff0c;因为在Sales_item类中定义了输入、输出和加法运算符&#xff0c;所以可以通过下述形式输出两个Sales_item…...

【Goalng】第九弹-----文件操作、JSON处理

&#x1f381;个人主页&#xff1a;星云爱编程 &#x1f50d;所属专栏&#xff1a;【Go】 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 长风破浪会有时&#xff0c;直挂云帆济沧海 目录 1.文件操作 1.1文件介绍 1.2.文件流 1.3.打开和关闭文件 1…...

锐评|希捷NVMe闪存+磁盘混合存储阵列

近日&#xff0c;希捷在英伟达GTC 2025会议上展示了NVMe混合闪存/磁盘阵列技术。这个混合存储阵列确实在当前AI数据存储困境中撕开了一道新口子&#xff0c;但远称不上完美&#xff0c;优缺点都极为鲜明。 从优点来看&#xff0c;希捷切中了大多数企业的痛点。AI领域数据量呈爆…...

如何缩短研发周期,降低研发成本?全星APQP软件为您提供解决方案

如何缩短研发周期&#xff0c;降低研发成本&#xff1f;全星APQP软件为您提供解决方案 一、 系统概述 全星研发管理APQP软件系统是一款专为产品研发和质量管控打造的智能化平台&#xff0c;旨在帮助企业高效推进APQP&#xff08;先期产品质量策划&#xff09;流程&#xff0c…...

Centos7安装cat美化工具lolcat

Centos7安装cat美化工具lolcat Centos7安装lolcat使用ruby安装lolcat配置cat系统别名 结果验证 Centos7安装lolcat lolcat &#xff1a;一个在Linux 终端中输出彩虹特效的命令行工具 使用ruby安装lolcat # 安装ruby和zip yum install -y ruby# 查看ruby版本 ruby --version# …...

bluecode-20240913_1_数据解码

时间限制&#xff1a;C/C 1000MS&#xff0c;其他语言 2000MS 内存限制&#xff1a;C/C 256MB&#xff0c;其他语言 512MB 难度&#xff1a;困难 数据解码 指定有一段经过编码的二进制数据&#xff0c;数据由0个或多个"编码单元"组成。"编码单元"的编码方式…...

【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的缓存技术:使用 Redis 提升性能

<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、开篇整…...

典范硬币系统(Canonical Coin System)→ 贪心算法

【典范硬币系统】 ● 典范硬币系统&#xff08;Canonical Coin System&#xff09;是指使用贪心算法总能得到最少硬币数量解‌的货币面值组合‌。 ● 给定一个硬币系统 &#xff0c;若使其为典范硬币系统&#xff0c;则要求其各相邻面值比例 &#xff0c;及各开区间 内各金额…...

hbuilderx打包iOS上传苹果商店的最简流程

无需Mac电脑&#xff0c;无需安装xcode和transporter&#xff0c;其实使用hbuilderx开发的ios软件&#xff0c;也可以上架到苹果的app store商店的。 只需要有苹果开发者中心的苹果开发者账号就行了。 假如你还在了解上架阶段&#xff0c;还没打包&#xff0c;也还没有创建任…...

DeepSeek详解:探索下一代语言模型

文章目录 前言一、什么是DeepSeek二、DeepSeek核心技术2.1 Transformer架构2.1.1 自注意力机制 (Self-Attention Mechanism)(a) 核心思想(b) 计算过程(c) 代码实现 2.1.2 多头注意力 (Multi-Head Attention)(a) 核心思想(b) 工作原理(c) 数学描述(d) 代码实现 2.1.3 位置编码 (…...

python的内存管理

目录 1. 引用计数 2. 垃圾收集&#xff08;GC&#xff09; python的内存管理主要是引用计数和垃圾回收器来进行内存管理 1. 引用计数 每个 Python 对象都有一个引用计数&#xff0c;当引用计数为零时&#xff0c;对象的内存会被释放。 import sysa [] # 创建一个空列表对…...

【STL】list

l i s t list list 是 C C C 标准模板库&#xff08; S T L STL STL&#xff09;中的一个序列容器&#xff08; S e q u e n c e C o n t a i n e r Sequence\ Container Sequence Container&#xff09;&#xff0c;它允许在容器的任意位置快速插入和删除元素&#xff0c;是一…...

证券公司主要业务分析及当前佣金最低免五情况探讨

我是StockMasterX&#xff0c;今日想分析证券公司主要业务&#xff0c;并探讨当前佣金最低且免五的证券公司情况&#xff0c;此议题具有一定研究价值&#xff0c;我从事股票交易多年&#xff0c;与证券公司互动频繁&#xff0c;前日晚间饮茶之际&#xff0c;浏览手机时对此深思…...

C++ 变量的声明与定义分离式编译与静态类型(十六)

1. 声明与定义的区别 声明&#xff08;declaration&#xff09;&#xff1a;向编译器表明某个变量&#xff08;或其他实体&#xff09;的类型与名字&#xff0c;使它在后续的编译过程中可见或可用。定义&#xff08;definition&#xff09;&#xff1a;除了声明变量的名字和类…...

黑盒测试的等价类划分法(输入数据划分为有效的等价类和无效的等价类)

重点: 有效等价和单个无效等价各取1个即可 1、正向用例:一条尽可能覆盖多条2、逆向用例:每一条数据&#xff0c;都是一条单独用例。 步骤: 1、明确需求 2、确定有效和无效等价 3、根据有效和无效造数据编写用例 3、适用场景 针对:需要有大量数据测试输入&#xff0c; …...

通过Appium理解MCP架构

MCP即Model Context Protocol&#xff08;模型上下文协议&#xff09;&#xff0c;是由Anthropic公司于2024年11月26日推出的开放标准框架&#xff0c;旨在为大型语言模型与外部数据源、工具及系统建立标准化交互协议&#xff0c;以打破AI与数据之间的连接壁垒。 MCP架构与Appi…...

uWebSockets开发入门

一、常用C++ WebSocket开源库 一些常用的 C++ WebSocket 开源库,它们支持 WebSocket 协议的实现,适用于客户端或服务器端开发。 1. Boost.Beast (推荐) 特点:基于 Boost.Asio 的高性能库,支持 HTTP/WebSocket,属于 Boost 官方库的一部分,稳定且跨平台。 适用场景:需要高…...

Python自动化模块:开启高效编程新时代

一、写在前面 在数字化时代&#xff0c;自动化技术已成为提高效率、降低成本的关键手段。Python 作为一种简洁、高效且功能强大的编程语言&#xff0c;凭借其丰富的库和框架&#xff0c;在自动化领域占据了举足轻重的地位&#xff0c;成为众多开发者的首选工具之一。从简单的文…...

Android7 Input(二)Linux 驱动层输入事件管理

概述 在Linux系统中&#xff0c;将键盘&#xff0c;鼠标&#xff0c;触摸屏等这类交互设备交由Linux Input子系统进行管理&#xff0c;Linux Input驱动子系统由于具有良好的和用户空间交互的接口。因此Linux Input驱动子系统&#xff0c;不止于只管理输入类型的设备。也可以将其…...

前端给后端发送数据时都需要包含哪些内容?(HTTP请求的基本组成部分)

1 [TOC](1)一、**必须传递的内容**1. **URL&#xff08;请求地址&#xff09;** 二、**可选内容**1. **请求方法&#xff08;HTTP Method&#xff09;**2. **请求头&#xff08;Headers&#xff09;**3. **请求体&#xff08;Body&#xff09;**4. **其他配置** 技术无关 一、必…...

记录vite引入sass预编译报错error during build: [vite:css] [sass] Undefined variable.问题

vite.config.ts resolve: {alias: {: path.resolve(__dirname, src),},},css: {// css预处理器preprocessorOptions: {scss: {additionalData: use "/assets/styles/block.scss" as *;,}}},block.scss $colorGreen: #00ff00;index.vue :v-deep .font-size-14{colo…...

智慧运维平台:赋能未来,开启高效运维新时代

在当今数字化浪潮下&#xff0c;企业IT基础设施、工业设备及智慧城市系统的复杂度与日俱增&#xff0c;传统人工运维方式已难以满足高效、精准、智能的管理需求。停机故障、低效响应、数据孤岛等问题直接影响企业运营效率和成本控制。大型智慧运维平台&#xff08;AIOps, Smart…...

【log4j】配置Slf4j

配置Slf4j 引入lombok包 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.36</version><scope>provided</scope> </dependency>引入log4j相关api <dependency…...

静态网页应用开发环境搭建实战教程

1. 前言 静态网页开发是前端工程师的基础技能之一&#xff0c;无论是个人博客、企业官网还是简单的Web应用&#xff0c;都离不开HTML、CSS和JavaScript。搭建一个高效的开发环境&#xff0c;能够极大提升开发效率&#xff0c;减少重复工作&#xff0c;并优化调试体验。 本教程…...

AP 场景架构设计(一) :OceanBase 读写分离策略解析

说明&#xff1a;本文内容对应的是 OceanBase 社区版&#xff0c;架构部分不涉及企业版的仲裁副本功能。OceanBase社区版和企业版的能力区别详见&#xff1a; 官网链接。 概述​ 当两种类型的业务共同运行在同一个数据库集群上时&#xff0c;这对数据库的配置等条件提出了较高…...

未来村庄智慧灯杆:点亮乡村智慧生活​

在乡村振兴与数字乡村建设的时代进程中&#xff0c;未来村庄智慧灯杆凭借其多功能集成与智能化特性&#xff0c;已成为乡村基础设施建设领域的崭新焦点&#xff0c;为乡村生活带来了前所未有的便利&#xff0c;推动着乡村生活模式的深刻变革。​ 多功能集成&#xff1a;一杆多能…...

MySQL基础语法DDLDML

目录 #1.创建和删除数据库 ​#2.如果有lyt就删除,没有则创建一个新的lyt #3.切换到lyt数据库下 #4.创建数据表并设置列及其属性,name是关键词要用name包围 ​编辑 #5.删除数据表 #5.查看创建的student表 #6.向student表中添加数据,数据要与列名一一对应 #7.查询studen…...

利用 VSCode 配置提升 vibe coding 开发效率

利用 VSCode 配置提升 vibe coding 开发效率 Vibe Coding&#xff08;氛围编程&#xff09;是一种基于AI的编程方法&#xff0c;其核心在于通过自然语言描述软件需求&#xff0c;再由大规模语言模型&#xff08;LLM&#xff09;自动生成代码&#xff0c;从而实现对传统手写编程…...

使用 Chromedp 监听网页请求和响应

使用 Chromedp 监听网页请求和响应 在进行网络爬虫的时候&#xff0c;有很多网站都有反爬机制&#xff0c;比如你想抓点数据&#xff0c;结果发现每次请求都带一堆奇奇怪怪的参数 —— 什么 timestamp 签名、AES 加密的字段&#xff0c;还有各种 Token 令牌&#xff0c;跟密码…...

AB包介绍及导出工具实现+AB包资源简单加载

Resource原理 项目中建立Resources目录&#xff0c;资源导入内部 生成项目包 资源文件存储路径 结论&#xff1a;存储在Resources下的资源&#xff0c;最终会存储在游戏的主体包中&#xff0c;发送给用户&#xff0c;手机系统上&#xff0c;如果需要做资源的更新&#xff0c;是…...

TCP/IP协议簇

文章目录 应用层http/httpsDNS补充 传输层TCP1. 序列号与确认机制2. 超时重传3. 流量控制&#xff08;滑动窗口机制&#xff09;4. 拥塞控制5. 错误检测与校验6. 连接管理总结 网络层ARP**ARP 的核心功能**ARP 的工作流程1. ARP 请求&#xff08;Broadcast&#xff09;2. ARP 缓…...

vector的模拟实现01

文章目录 vector的模拟实现构造函数析构函数迭代器容量sizecapacityreverse 遍历下标[] 修改push_backpop_backinsert 结语 我们大家有又见面了&#xff0c;给生活加点</font color red>impetus&#xff01;&#xff01;开启今天的编程之路 今天我们来学习vector。了解一…...

信息学奥赛一本通 1609:【例 4】Cats Transport | 洛谷 CF311B Cats Transport

【题目链接】 ybt 1609&#xff1a;【例 4】Cats Transport 洛谷 CF311B Cats Transport 【题目考点】 1. 动态规划&#xff1a;斜率优化动规 【解题思路】 解法1&#xff1a;设a点的前缀和 输入的 d d d序列是从 d 2 d_2 d2​到 d n d_n dn​&#xff0c;共n-1个数字。人…...

shared_ptr和 weak_ptr的详细介绍

关于 shared_ptr 和 weak_ptr 的详细介绍及使用示例&#xff1a; 1. shared_ptr&#xff08;共享所有权智能指针&#xff09; 核心特性 引用计数&#xff1a;记录当前有多少个 shared_ptr 共享同一个对象。自动释放&#xff1a;当引用计数归零时&#xff0c;自动释放对象内存…...

electron打包vue2项目流程

1&#xff0c;安装一个node vue2 的项目 2&#xff0c;安装electron&#xff1a; npm install electron -g//如果安装还是 特比慢 或 不想安装cnpn 淘宝镜像查看是否安装成功&#xff1a;electron -v 3&#xff0c;进入到项目目录&#xff1a;cd electron-demo 进入项目目录…...

Baklib驱动企业知识管理数字化转型

Baklib驱动知识资产激活 在信息碎片化与数据爆炸的产业环境下&#xff0c;企业知识中台正成为重构组织智慧的核心枢纽。Baklib通过构建全生命周期知识管理模型&#xff0c;将分散于邮件、文档及协作系统的非结构化数据转化为可检索、可分析的标准化资产。其内置的智能分类引擎…...

Elasticsearch 高级

Elasticsearch 高级 建议阅读顺序&#xff1a; Elasticsearch 入门Elasticsearch 搜索Elasticsearch 搜索高级Elasticsearch高级&#xff08;本文&#xff09; 1. nested 类型 1.1 介绍 Elasticsearch 中的 nested 类型允许你在文档内存储复杂的数据结构&#xff0c;比如一个…...

1--当「穷举」成为艺术:CTF暴力破解漏洞技术从入门到入刑指南(知识点讲解版)

当「穷举」成为艺术&#xff1a;CTF暴力破解漏洞技术从入门到入刑指南 引言&#xff1a;论暴力破解的哲学意义 “世界上本没有漏洞&#xff0c;密码设得简单了&#xff0c;便成了漏洞。” —— 鲁迅&#xff08;并没有说过&#xff09; 想象你是个不会撬锁的小偷&#xff0c;面…...

jdk 支持路线图

https://www.oracle.com/java/technologies/java-se-support-roadmap.html 按照路线图得知&#xff0c;在2025.09 发布openjdk 25&#xff0c;是一个LTS版本。...

VsCode启用右括号自动跳过(自动重写) - 自录制gif演示

VsCode启用右括号自动跳过(自动重写) - 自录制gif演示 前言 不知道大家在编程时候的按键习惯是怎样的。输入完左括号后编辑器一般会自动补全右括号&#xff0c;输入完左括号的内容后&#xff0c;是按→跳过右括号还是按)跳过右括号呢&#xff1f; for (int i 0; i < a.s…...

Android设计模式之模板方法模式

一、定义&#xff1a; 定义一个操作中的算法的框架&#xff0c;而将一些步骤延迟到子类中&#xff0c;使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 二、结构&#xff1a; AbstractClass抽象类&#xff1a;定义算法的骨架&#xff0c;包含模板方法和若干…...

纯个人整理,蓝桥杯使用的算法模板day1(dfs、bfs)

算法索引 dfs&#xff08;深度优先搜索&#xff09;bfs&#xff08;广度优先搜索&#xff09;迷宫树结构 dfs&#xff08;深度优先搜索&#xff09; 功能&#xff1a; 适合搜索所有的解 代码模板&#xff1a; class Solution{public void dfs(int[][] graph, int i, int j){i…...