feat: 添加g3fo-commit-jira skill

This commit is contained in:
2026-03-16 18:11:34 +08:00
parent 2768d58aa3
commit dc2d6697af
13 changed files with 960 additions and 24 deletions
@@ -230,6 +230,83 @@ sentinel deny-scripts-reconfig yes
| `sentinel failover-timeout` | 故障转移超时时间 | `180000` |
| `sentinel announce-ip` | 宣告哨兵外部 IP | 宿主机实际 IP |
### 4.3 哨兵数量与 Master 选举
#### 如何选出新的 Redis Master(故障转移)
这里的「Master」指 **Redis 主节点**(可写的那台),不是哨兵本身。流程简述如下:
1. **判定主节点下线**
每个哨兵定期探测 Redis 主节点。当某个哨兵认为主节点 **主观下线(SDOWN)** 后,会向其他哨兵询问;当达到 **quorum** 个哨兵都认为主节点不可达时,主节点被判定为 **客观下线(ODOWN)**。
2. **选举 Sentinel 领导者**
哨兵之间通过 Raft 式选举选出一个 **Leader**,由它来执行后续故障转移(只会有唯一一个 Sentinel 在执行 failover)。
3. **选出新的 Redis Master**
Leader 在**当前存活的从节点**中选一个提升为新主,选择规则通常为:
- 若配置了 `replica-priority`(哨兵侧为 `sentinel replica-priority`),优先选优先级最高且可达的从节点;
- 否则按**复制偏移量**优先选数据最新的从节点;
- 再按 `runid` 字典序等做 tie-break。
选好后向该从节点下发 `REPLICAOF NO ONE`,使其成为新主,其余从节点改为复制新主。
所以:**“选出 master 节点” = 由 Sentinel Leader 在从节点里按优先级/复制进度选一个,并执行提升为主。**
#### 是否一定要三台哨兵以上?
| 哨兵数量 | quorum 典型值 | 说明 |
|----------|----------------|------|
| **1 台** | 1 | 可以触发故障转移,但哨兵单点故障则无人做 failover,**不推荐生产**。 |
| **2 台** | 1 或 2 | quorum=1:能 failover,但两台意见不一致时可能脑裂;quorum=2:需两台都同意才 failover,任一台宕机则永远达不到 2,**无法触发故障转移**。 |
| **3 台** | **2** | 至少 2 台同意才客观下线并执行 failover;允许 1 台哨兵宕机仍可完成选举与切换,**生产推荐最少 3 台 + quorum=2**。 |
| 5 台 | 3 | 可容忍 2 台哨兵同时宕机。 |
**结论**:
- **不是“必须大于 3 台”**,但 **1 台无高可用、2 台难以兼顾安全与可用**,因此 **至少 3 台哨兵 + quorum=2** 是常见最小生产配置,这样既能选出新 master,又能在挂掉 1 台哨兵时继续工作。
quorum 在配置里即 `sentinel monitor mymaster <ip> <port> <quorum>` 的最后一个数字,例如:
```Properties
sentinel monitor mymaster 192.168.3.200 6379 2
```
表示至少 **2 个**哨兵认为主节点下线,才会触发客观下线和后续的 Master 选举与故障转移。
#### 两哨兵存活却未选出主节点时的排查
当前是**两台 Redis 主机 + 两台哨兵**且两台哨兵都存活时,若一直没选出新主,可按下面逐项查。
1. **quorum 是否已达到**
客观下线(ODOWN)需要至少 quorum 个哨兵认为主节点下线,才会进入故障转移。
- 若配置是 `sentinel monitor mymaster ... 2`,则**两台哨兵都必须**认为主节点不可达。
- 在**两台哨兵上分别**执行,看主节点是否已被判为客观下线(`flags` 里是否有 `o_down`):
```bash
redis-cli -h <哨兵1_IP> -p 26379 -a <密码> SENTINEL master mymaster
redis-cli -h <哨兵2_IP> -p 26379 -a <密码> SENTINEL master mymaster
```
- 若只有一台认为 down,另一台仍认为 master 存活,则不会 ODOWN,也就不会触发选举。常见原因:网络分区、或两台哨兵到原主节点的网络表现不一致。
2. **是否有可提升的从节点**
新主是从**当前从节点(replica)**里选出来的;若哨兵认为没有可用从节点,就不会选出新主。
- 在两台哨兵上任选一台执行:
```bash
redis-cli -h <哨兵IP> -p 26379 -a <密码> SENTINEL slaves mymaster
```
- 看列表是否为空、或从节点是否被标成 `s_down`/`o_down`。若从节点也被判下线或复制链路断开,哨兵不会提升它。
3. **法定人数与哨兵一致性**
执行(在两台哨兵上都跑一次):
```bash
redis-cli -h <哨兵IP> -p 26379 -a <密码> SENTINEL ckquorum mymaster
```
- 若提示 quorum 未满足,说明当前“认为主节点下线”的哨兵数不足,不会触发故障转移。
4. **quorum 配置是否过大**
若当时部署时按 3 台哨兵配了 `quorum=2`,现在只剩 2 台,理论上 2 台都同意即可达到 quorum=2。但若误配成 **quorum=3**,则 2 台永远达不到 3,**不会**触发客观下线和选举。检查每台哨兵的 `sentinel.conf` 里 `sentinel monitor mymaster ...` 最后一个数字是否为 2(2 台哨兵时建议为 2)。
5. **等待时间**
主节点需在 **down-after-milliseconds**(如 30000)内一直被判定不可达,才会主观下线,再经 quorum 达成客观下线。刚宕机后需至少等够这段时间再看是否选出新主。
**小结**:两哨兵存活仍不选主,多半是 **(1) quorum 未达成**(两台对主节点状态看法不一致)或 **(2) quorum 配成 3**,或 **(3) 从节点被哨兵判为不可用**。先查 `SENTINEL master mymaster` 的 flags、`SENTINEL slaves mymaster` 和 `SENTINEL ckquorum mymaster`,再对照上述几条处理。
---
@@ -256,8 +333,8 @@ spring:
# --- DB ---
database: ${app.redis-database:0} # 选择 DB(0~15,取决于你的 redis 配置)
# --- 启动检查 / 发现 ---
checkSentinelsList: true # 启动时校验 Sentinel 列表(默认 true)
# --- 启动检查 / 发现(单哨兵宕机不影响业务必读)---
checkSentinelsList: false # 建议 false:启动/刷新时不强制校验“全部”哨兵,任一只哨兵宕机不会导致客户端整体不可用(默认 true 会连所有哨兵,一个不通就报错)
sentinelsDiscovery: true # 是否自动发现更多 sentinel(默认 true;Docker/NAT 环境可考虑关掉避免“拓扑污染”)
dnsMonitoringInterval: 5000 # DNS 变更监控间隔 ms;-1 表示禁用(对域名方式接入有用)
@@ -359,4 +436,116 @@ spring:
---
## 八、单哨兵宕机不影响业务(Redisson 配置)
### 8.1 现象与原因
当**只停止一个哨兵节点**时,若出现:
- `No route to host: 192.168.3.110/192.168.3.110:26379`(其中 110 为已停的哨兵)
- 或 `RedisReadonlyException: READONLY You can't write against a read only replica`(写到了已变为 replica 的旧 master)
**主要原因**是 Redisson 的以下行为:
| 配置项 | 默认值 | 导致“单哨兵挂则全挂”的原因 |
|--------|--------|----------------------------|
| **checkSentinelsList** | `true` | 启动或周期性刷新时会对**配置中的每一个**哨兵执行校验/连接;任一哨兵不可达(如 110 已停)会触发异常或阻塞,导致客户端无法正常从其余哨兵获取当前 master,进而整体不可用或拿到过期拓扑。 |
`RedisReadonlyException` 通常表示**已经发生过故障转移**(当前写到的 192.168.3.200 已被降为 replica),而客户端因上述原因无法从存活的哨兵刷新到新 master,仍向旧主写,从而报只读。
### 8.2 推荐配置(单哨兵宕机不影响业务)
在 Nacos/应用配置中,将 Redisson 的哨兵相关配置改为:
```yaml
sentinelServersConfig:
masterName: "mymaster"
sentinelAddresses:
- "redis://192.168.3.230:26379"
- "redis://192.168.3.200:26379"
- "redis://192.168.3.110:26379"
# 关键:单哨兵宕机时仍可从其余哨兵获取 master,不影响业务
checkSentinelsList: false # 不强制校验“全部”哨兵,任一只不可达不会拖垮客户端
sentinelsDiscovery: true # 按需保留;Docker/NAT 环境若出现拓扑混乱可改为 false
```
**要点**:
- **checkSentinelsList: false**:不再要求能连上配置里的每一个哨兵,只要有一个哨兵可用即可获取 master 并刷新拓扑,单哨兵停机不会导致业务不可用。
- 保留多个 `sentinelAddresses`:多个哨兵仍可做高可用,只是客户端不会因“其中一个连不上”而整体失败。
### 8.3 为什么 SENTINEL masters 显示 200 却无法写入?
`SENTINEL masters` 列出的是哨兵**当前记录的主节点信息**,但在以下情况下会出现“查到的是 200,却写不进去”:
1. **200 已被降级为副本**
故障转移后,192.168.3.200 可能已经执行了 `REPLICAOF` 指向新主,自身变为只读副本。此时 `SENTINEL masters` 里可能仍显示 `ip 192.168.3.200`(视图未刷新或不同哨兵收敛有先后),但连上 200 执行写会报 `READONLY`。
2. **应看“当前主节点”而非仅看 masters 表**
用下面命令取的是**当前可写主节点**,比 `SENTINEL masters` 更贴近实际:
```bash
redis-cli -h 192.168.3.230 -p 26379 -a afe123456 SENTINEL get-master-addr-by-name mymaster
```
若返回的是**另一台**(例如 192.168.3.xxx),说明新主已切换,应连该地址写。
3. **在 200 上自检角色**
直连 200(你环境里 Redis 端口为 16379):
```bash
redis-cli -h 192.168.3.200 -p 16379 -a afe123456 ROLE
```
若返回 `slave`,说明 200 已是副本,只能读不能写;写请求应发往 `get-master-addr-by-name` 返回的那台。
**小结**:查到是 200 却不能写,多半是 200 已是 replica。用 `SENTINEL get-master-addr-by-name mymaster` 确认当前主,并连该主写;应用侧在 `checkSentinelsList: false` 且能连上任意存活哨兵时会自动刷新到新主。
### 8.4 故障转移后的核对
若已出现 `s_down,o_down` 或 `role-reported: slave`,说明哨兵已做过故障转移。建议在**仍存活的**哨兵上确认当前主节点:
```bash
redis-cli -h 192.168.3.230 -p 26379 -a afe123456 SENTINEL get-master-addr-by-name mymaster
```
应用在能连上任意存活哨兵且 `checkSentinelsList: false` 时,会通过拓扑刷新自动指向新 master,无需改配置。
### 8.5 双节点均为 slave(复制环)的排查与处理
当两台 Redis 主机在 `ROLE` 下均显示为 `slave`,且互相把对方当作 master 时,形成**复制环**:没有真正的主节点,所有写请求都会报 `READONLY`。
**典型表现**(示例 IP/端口可替换为实际环境):
- 192.168.3.200:16379 执行 `ROLE` → `slave`,master 指向 192.168.3.230:6379
- 192.168.3.230:6379 执行 `ROLE` → `slave`,master 指向 192.168.3.200:16379
常见原因:多次故障转移、手动改过 `replicaof`、或 Sentinel 在异常情况下写入了错误的主从关系。
**处理步骤(人工指定主从)**:
1. **选定一台作为唯一 master**(示例以 192.168.3.230 为主,端口按实际为准)
在该节点上执行:
```bash
redis-cli -h 192.168.3.230 -p 6379 -a <密码> REPLICAOF NO ONE
```
执行后该节点成为唯一可写主节点。
2. **将另一台设为该主的从节点**(示例为 192.168.3.200 作为 230 的从)
在从节点上执行(端口与上一步一致):
```bash
redis-cli -h 192.168.3.200 -p 16379 -a <密码> REPLICAOF 192.168.3.230 6379
```
3. **校验**
- 在主节点上执行 `ROLE`,应看到 `master`。
- 在从节点上执行 `ROLE`,应看到 `slave`,且 master 为刚指定的主节点地址与端口。
4. **哨兵**
Sentinel 会通过心跳发现新的主从拓扑;若长时间未更新,可在当前主节点所在机器重启该机 Sentinel,或按需执行 `SENTINEL failover`(拓扑已正确时一般无需执行)。
**注意**:端口需与现网一致(如 200 使用 16379、230 使用 6379 时,上述命令中的端口要对应修改)。
---
**参考资料**:[Redisson 官方配置文档](https://redisson.pro/docs/configuration/#sentinel-yaml-config-format)