Initial commit with project setup and basic structure established.
This commit is contained in:
@@ -0,0 +1,336 @@
|
||||
# Redis Sentinel 高可用架构部署与运维手册
|
||||
|
||||
## 一、概述
|
||||
### 1.1 核心功能
|
||||
Redis Sentinel(哨兵)是 Redis 的高可用解决方案。其核心目标是实现主从切换的自动化,确保系统在主节点故障时能够自动选举新的主节点并恢复服务。
|
||||
|
||||
### 1.2 适用场景
|
||||
- 生产环境下的 Redis 高可用需求。
|
||||
- 需要自动故障转移(Failover)的分布式系统。
|
||||
- 读写分离架构。
|
||||
|
||||
### 1.3 前置条件
|
||||
- **运行环境**:Docker & Docker Compose。
|
||||
- **镜像版本**:推荐使用 Redis 8.4.0 及以上版本。
|
||||
- **网络规划**:所有节点需网络互通,且需明确各宿主机的外部 IP。
|
||||
|
||||
---
|
||||
|
||||
## 二、环境准备
|
||||
在所有节点(主节点、从节点、哨兵节点)上执行目录初始化及权限设置。
|
||||
|
||||
### 2.1 目录结构配置
|
||||
```bash
|
||||
# 创建配置、数据、日志目录
|
||||
mkdir -p /data/redis/{conf,data,logs}
|
||||
|
||||
# 权限初始化(针对 Redis 容器默认用户 999)
|
||||
chown -R 999:999 /data/redis
|
||||
chmod -R 750 /data/redis
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、部署流程
|
||||
|
||||
### 3.1 Docker 服务编排
|
||||
使用 Docker Compose 部署 Redis 服务及 Sentinel 节点。
|
||||
|
||||
**docker-compose.yml 示例:**
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# Redis 节点容器
|
||||
redis:
|
||||
image: redis:8.4.0
|
||||
container_name: redis
|
||||
restart: always
|
||||
ports:
|
||||
- "6379:6379"
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /data/redis/conf:/etc/redis
|
||||
- /data/redis/data:/data
|
||||
- /data/redis/logs:/var/log/redis
|
||||
command: redis-server /etc/redis/redis.conf
|
||||
networks:
|
||||
- redis-net
|
||||
|
||||
# Sentinel 节点容器
|
||||
redis-sentinel:
|
||||
image: redis:8.4.0
|
||||
container_name: redis-sentinel
|
||||
restart: always
|
||||
ports:
|
||||
- "26379:26379"
|
||||
volumes:
|
||||
- /data/redis/conf:/etc/redis
|
||||
- /data/redis/logs:/var/log/redis
|
||||
command: redis-sentinel /etc/redis/sentinel.conf
|
||||
networks:
|
||||
- redis-net
|
||||
|
||||
networks:
|
||||
redis-net:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、核心配置说明
|
||||
|
||||
### 4.1 Redis 服务端配置 (`redis.conf`)
|
||||
```Properties
|
||||
# 基础配置
|
||||
bind 0.0.0.0
|
||||
# 需被远程连接,关闭这配置
|
||||
protected-mode no
|
||||
port 6379
|
||||
# 指定广播地址,即使 Docker 内部获取到的是 172.x,也强制告诉 Sentinel 我是 ${REDIS_MASTER_IP}
|
||||
replica-announce-ip ${REDIS_MASTER_IP}
|
||||
replica-announce-port 6379
|
||||
|
||||
# Docker中禁止后台运行(由容器管理)
|
||||
daemonize no
|
||||
pidfile /var/run/redis.pid
|
||||
logfile /var/log/redis/redis.log
|
||||
# 容器内数据目录(对应宿主机/data/redis/data)
|
||||
dir /data
|
||||
|
||||
# 密码配置(建议修改为自己的密码)
|
||||
requirepass afe123456
|
||||
# 允许从节点同步时使用的密码
|
||||
masterauth afe123456
|
||||
|
||||
# 持久化配置(按需调整,默认开启RDB)
|
||||
# 当满足 “900 秒(15 分钟)内发生至少 1 次写操作” 时,触发 RDB 持久化(将内存中的数据快照写入磁盘)
|
||||
save 900 1
|
||||
save 300 10
|
||||
save 60 10000
|
||||
# 开启 RDB 文件的压缩功能
|
||||
rdbcompression yes
|
||||
# 指定 RDB 快照文件的名称
|
||||
dbfilename dump.rdb
|
||||
|
||||
# 主从复制配置(AP1是主节点,无需配置replicaof)
|
||||
# 开启无盘同步(减少磁盘IO)
|
||||
repl-diskless-sync yes
|
||||
# 无盘同步的延迟时间(单位:秒,默认值为 5)
|
||||
repl-diskless-sync-delay 5
|
||||
# 复制积压缓冲区(动态扩容,Redis 8.4默认支持)
|
||||
repl-backlog-size 1mb
|
||||
|
||||
# 其他优化配置
|
||||
# 内存满时淘汰策略
|
||||
maxmemory-policy allkeys-lru
|
||||
# 1. 开启 AOF 持久化
|
||||
appendonly yes
|
||||
# 2. 指定 AOF 文件名(Redis 7+ 这是一个目录名的一前缀)
|
||||
appendfilename "appendonly.aof"
|
||||
# 3. 开启混合持久化 (核心配置)
|
||||
# 在 AOF 重写时,会先写入 RDB 格式的快照,再追加增量指令
|
||||
aof-use-rdb-preamble yes
|
||||
# 4. 刷盘策略 (性能与安全的平衡)
|
||||
# 每秒刷盘一次,意味着死机最多丢失 1 秒的数据
|
||||
appendfsync everysec
|
||||
# 5. 重写触发机制 (防止文件无限膨胀)
|
||||
# 当 AOF 文件比上次重写后大小增长 100% 且文件大于 64MB 时触发重写
|
||||
auto-aof-rewrite-percentage 100
|
||||
auto-aof-rewrite-min-size 64mb
|
||||
|
||||
notify-keyspace-events AE
|
||||
```
|
||||
从节点添加配置
|
||||
```Properties
|
||||
# 指定广播地址,即使 Docker 内部获取到的是 172.x,也强制告诉 Sentinel 我是 ${REDIS_SLAVE_IP}
|
||||
replica-announce-ip ${REDIS_SLAVE_IP}
|
||||
replica-announce-port 6379
|
||||
# 核心:指定主节点(AP1的IP和端口)
|
||||
replicaof ${REDIS_MASTER_IP} 6379
|
||||
# 从节点只读(默认开启,避免误写)
|
||||
replica-read-only yes
|
||||
```
|
||||
以下为生产环境推荐的核心配置项:
|
||||
|
||||
| 配置项 | 说明 | 推荐值 |
|
||||
| :--- | :--- | :--- |
|
||||
| `bind` | 绑定 IP 地址 | `0.0.0.0` |
|
||||
| `protected-mode` | 保护模式 | `no` |
|
||||
| `port` | 监听端口 | `6379` |
|
||||
| `replica-announce-ip` | 宣告外部 IP(解决 Docker NAT 问题) | 宿主机实际 IP |
|
||||
| `requirepass` | 服务访问密码 | 自定义强密码 |
|
||||
| `masterauth` | 主从同步授权密码 | 与 `requirepass` 一致 |
|
||||
| `appendonly` | 开启 AOF 持久化 | `yes` |
|
||||
| `aof-use-rdb-preamble` | 开启混合持久化 | `yes` |
|
||||
|
||||
> **注意:** 在从节点配置中,必须包含 `replicaof <master-ip> 6379` 以建立主从关系。
|
||||
|
||||
### 4.2 哨兵配置 (`sentinel.conf`)
|
||||
```Properties
|
||||
# 基础配置
|
||||
bind 0.0.0.0
|
||||
protected-mode no
|
||||
port 26379
|
||||
|
||||
# 强制向其他哨兵和客户端宣告自己的外部IP,从节点需要修复对应自主机IP
|
||||
sentinel announce-ip ${REDIS_MASTER_IP}
|
||||
sentinel announce-port 26379
|
||||
|
||||
# Docker中禁止后台运行
|
||||
daemonize no
|
||||
logfile /var/log/redis/sentinel.log
|
||||
dir /tmp
|
||||
|
||||
# 监控主节点(名称mymaster,主节点IP=AP1的IP,端口6379,quorum=2)
|
||||
sentinel monitor mymaster ${REDIS_MASTER_IP} 6379 2
|
||||
|
||||
# 主节点密码(与Redis主节点一致)
|
||||
sentinel auth-pass mymaster afe123456
|
||||
|
||||
# 故障检测超时时间(30秒,可调整)
|
||||
sentinel down-after-milliseconds mymaster 30000
|
||||
|
||||
# 故障转移时,最多1个从节点同时同步新主节点(避免带宽占用过高)
|
||||
sentinel parallel-syncs mymaster 1
|
||||
|
||||
# 故障转移超时时间(180秒)
|
||||
sentinel failover-timeout mymaster 180000
|
||||
|
||||
# 禁止Sentinel在故障转移后自动重配置主节点(Docker环境下无需开启)
|
||||
sentinel deny-scripts-reconfig yes
|
||||
```
|
||||
哨兵节点用于监控主节点状态并协调切换。
|
||||
|
||||
| 配置项 | 说明 | 示例值 |
|
||||
| :--- | :--- | :--- |
|
||||
| `sentinel monitor` | 监控主节点(名称、IP、端口、法定人数) | `mymaster ${REDIS_MASTER_IP} 6379 2` |
|
||||
| `sentinel auth-pass` | 主节点访问密码 | `mymaster afe123456` |
|
||||
| `sentinel down-after-milliseconds` | 故障判定超时时间(毫秒) | `30000` |
|
||||
| `sentinel failover-timeout` | 故障转移超时时间 | `180000` |
|
||||
| `sentinel announce-ip` | 宣告哨兵外部 IP | 宿主机实际 IP |
|
||||
|
||||
---
|
||||
|
||||
## 五、客户端集成(Redisson)
|
||||
在 Spring Boot 应用中,使用 Redisson 实现哨兵模式的连接:
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
redis:
|
||||
redisson:
|
||||
config: |
|
||||
sentinelServersConfig:
|
||||
masterName: "mymaster" # Sentinel 里监控主库的名字(sentinel monitor <name> ...)
|
||||
sentinelAddresses: # Sentinel 节点地址列表(redis://host:port)
|
||||
- "redis://${REDIS_MASTER_IP}:26379"
|
||||
- "redis://${REDIS_SLAVE_IP}:26379"
|
||||
- "redis://${REDIS_SENTINEL_3_IP}:26379"
|
||||
|
||||
# --- 认证(Redis 6+ ACL 也可用 username)---
|
||||
password: "afe123456" # Redis 主从节点密码(requirepass / ACL 密码)
|
||||
sentinelPassword: "afe123456" # Sentinel 密码(requirepass / ACL 密码);若与 password 相同也可省略
|
||||
|
||||
# --- DB ---
|
||||
database: ${app.redis-database:0} # 选择 DB(0~15,取决于你的 redis 配置)
|
||||
|
||||
# --- 启动检查 / 发现 ---
|
||||
checkSentinelsList: true # 启动时校验 Sentinel 列表(默认 true)
|
||||
sentinelsDiscovery: true # 是否自动发现更多 sentinel(默认 true;Docker/NAT 环境可考虑关掉避免“拓扑污染”)
|
||||
dnsMonitoringInterval: 5000 # DNS 变更监控间隔 ms;-1 表示禁用(对域名方式接入有用)
|
||||
|
||||
# --- 读写/订阅模式 ---
|
||||
readMode: "MASTER" # 读策略:SLAVE / MASTER / MASTER_SLAVE
|
||||
subscriptionMode: "MASTER" # 订阅(pubsub)连接使用节点:SLAVE / MASTER
|
||||
checkSlaveStatusWithSyncing: true # 检查 slave 的 master-link-status=ok(默认 true)
|
||||
|
||||
# --- 负载均衡(可选,默认 RoundRobin)---
|
||||
# 注意:下面这种 !<class> 写法需要 YAML 标签支持(Redisson 原生 YAML 支持)
|
||||
loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {}
|
||||
|
||||
# --- 连接池(重要:这些是“每个节点”的池大小)---
|
||||
masterConnectionMinimumIdleSize: 24 # 每个 master 最小空闲连接数(默认 24)
|
||||
masterConnectionPoolSize: 64 # 每个 master 最大连接数(默认 64)
|
||||
slaveConnectionMinimumIdleSize: 24 # 每个 slave 最小空闲连接数(默认 24)
|
||||
slaveConnectionPoolSize: 64 # 每个 slave 最大连接数(默认 64)
|
||||
|
||||
# --- 订阅连接池(pubsub)---
|
||||
subscriptionConnectionMinimumIdleSize: 1 # 订阅连接最小空闲数(默认 1)
|
||||
subscriptionConnectionPoolSize: 50 # 订阅连接最大连接数(默认 50)
|
||||
subscriptionsPerConnection: 5 # 每条订阅连接允许的订阅数上限(默认 5)
|
||||
subscriptionTimeout: 7500 # 订阅超时 ms(默认 7500)
|
||||
|
||||
# --- 超时与重试 ---
|
||||
idleConnectionTimeout: 10000 # 连接空闲多久后可被回收 ms(默认 10000)
|
||||
connectTimeout: 10000 # 建连超时 ms(默认 10000)
|
||||
timeout: 6000 # 命令响应超时 ms(默认 3000,从成功发送命令后开始计时)
|
||||
retryAttempts: 4 # 命令发送失败重试次数(默认 4)
|
||||
|
||||
# --- 连接保活 ---
|
||||
pingConnectionInterval: 30000 # 定期 PING 检测死连接 ms;0 关闭(默认 30000)
|
||||
keepAlive: false # TCP keepAlive(默认 false)
|
||||
tcpNoDelay: true # TCP_NODELAY(默认 true)
|
||||
|
||||
# --- 故障 slave 处理 ---
|
||||
failedSlaveReconnectionInterval: 3000 # slave 断线后重连尝试间隔 ms(默认 3000)
|
||||
failedSlaveNodeDetector: !<org.redisson.client.FailedConnectionDetector> {}
|
||||
threads: 16 # Redisson 业务线程池(默认 16;监听/远程服务等)
|
||||
nettyThreads: 32 # Netty IO 线程(默认 32;0=CPU*2)
|
||||
transportMode: "NIO" # NIO / EPOLL / KQUEUE(默认 NIO)
|
||||
protocol: "RESP2" # RESP2 / RESP3(默认 RESP2)
|
||||
|
||||
# 编解码器(默认 Kryo5Codec;你用 JsonJacksonCodec 也可以)
|
||||
codec:
|
||||
class: "org.redisson.codec.JsonJacksonCodec"
|
||||
# 分布式锁看门狗(默认 30000ms;无 leaseTimeout 的锁依赖它续期)
|
||||
lockWatchdogTimeout: 30000
|
||||
|
||||
# 其他通用项(按需)
|
||||
lazyInitialization: false # true=首次用到才连接;false=启动即连接
|
||||
useThreadClassLoader: true # 解决部分容器 ClassNotFound 问题
|
||||
keepPubSubOrder: true # PubSub 消息是否保持到达顺序
|
||||
useScriptCache: true # Lua 脚本缓存
|
||||
# 下面这些是高级项/按需再开:
|
||||
valkeyCapabilities: [] # 例如 ["REDIRECT"]
|
||||
lockWatchdogBatchSize: 100
|
||||
checkLockSyncedSlaves: true
|
||||
slavesSyncTimeout: 1000
|
||||
reliableTopicWatchdogTimeout: 600000
|
||||
minCleanUpDelay: 5
|
||||
maxCleanUpDelay: 1800
|
||||
cleanUpKeysAmount: 100
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、运维常用命令
|
||||
|
||||
### 6.1 哨兵管理命令
|
||||
详细的 Redis 常用命令及 Sentinel 运维操作请参考:[Redis 常用命令使用指南](./usage.md)
|
||||
|
||||
通过 `redis-cli` 连接哨兵端口(默认 26379)执行:
|
||||
|
||||
| 命令 | 功能描述 |
|
||||
| :--- | :--- |
|
||||
| `SENTINEL masters` | 列出所有被监控的主节点状态 |
|
||||
| `SENTINEL master <name>` | 查看指定主节点的详细信息 |
|
||||
| `SENTINEL slaves <name>` | 查看指定主节点的从节点列表 |
|
||||
| `SENTINEL sentinels <name>` | 列出除当前节点外的其他哨兵实例 |
|
||||
| `SENTINEL get-master-addr-by-name <name>` | 获取当前有效的主节点 IP 和端口 |
|
||||
| `SENTINEL failover <name>` | **手动强制触发**故障转移 |
|
||||
| `SENTINEL reset <pattern>` | 重置配置,清除过期节点信息 |
|
||||
| `SENTINEL ckquorum <name>` | 检查当前哨兵数量是否满足法定人数 |
|
||||
|
||||
---
|
||||
|
||||
## 七、注意事项与最佳实践
|
||||
|
||||
> 注意:
|
||||
> 1. **脑裂保护**:建议配置 `min-replicas-to-write 1` 和 `min-replicas-max-lag 10`,确保主库至少有 1 个正常的从库时才允许写入,防止网络分区导致的数据丢失。
|
||||
> 2. **Docker 网络**:在容器环境下,务必配置 `replica-announce-ip` 和 `sentinel announce-ip`,否则哨兵可能会记录容器内部 IP 导致客户端无法连接。
|
||||
> 3. **持久化平衡**:推荐开启混合持久化(AOF + RDB),并设置 `appendfsync everysec` 以平衡性能与安全性。
|
||||
> 4. **权限细化**:生产环境建议将 `/data/redis` 目录权限进一步收紧,仅允许特定 UID 访问。
|
||||
|
||||
---
|
||||
**参考资料**:[Redisson 官方配置文档](https://redisson.pro/docs/configuration/#sentinel-yaml-config-format)
|
||||
Reference in New Issue
Block a user