redis 10.主从复制(主从复制原理、一主两从、去中心化,主节点shutdown从节点上位)

本文详细介绍了Redis的主从复制机制,包括一主两从的配置与操作,主从节点shutdown后的处理,以及复制原理。讨论了去中心化配置,使从节点能作为其他从节点的主节点,以及在主节点故障时如何实现从节点晋升为主节点。此外,还提到了复制过程中可能存在的数据延迟问题。


1. 主从复制概念

  主节点数据更新后,根据配置和策略, 自动同步到从节点的master/slaver机制,Master以写为主,Slave以读为主

在这里插入图片描述


2. 一主两从

前提:
  拷贝并重命名多个redis.conf文件供redis-server启动,include参数配置 公有的redis.conf((写绝对路径))
  设置Pid文件名字 pidfile
  指定端口port
  修改Log文件名字
  修改dump.rdb名字dbfilename
  开启daemonize yes
  Appendonly 关掉或者改名字

(1) 新建redis6379.conf

include /myredis/redis.conf
pidfile /var/run/redis_6379.pid
port 6379
dbfilename dump6379.rdb
logfile "/myredis/redis6379.log"

在这里插入图片描述

(2) 新建redis6380.conf

include /myredis/redis.conf
pidfile /var/run/redis_6380.pid
port 6380
dbfilename dump6380.rdb
masterauth 123456
logfile "/myredis/redis6380.log"

在这里插入图片描述

(3) 新建redis6381.conf

include /myredis/redis.conf
pidfile /var/run/redis_6381.pid
port 6381
dbfilename dump6381.rdb
masterauth 123456
logfile "/myredis/redis6381.log"

在这里插入图片描述

启动三台redis服务器,查看进程
在这里插入图片描述

查看三台主机运行情况

info replication

打印主从复制的相关信息
在这里插入图片描述

配从(库)不配主(库)

slaveof  <ip><port>

成为某个实例的从服务器
1、在6380和6381上执行: slaveof 127.0.0.1 6379
在这里插入图片描述
在这里插入图片描述
6379端口代表的redis称为主节点
在这里插入图片描述

2、在主机上写,在从机上可以读取数据
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在从机上写数据报错
在这里插入图片描述

3、主机挂掉,重启就行,一切如初
4、从机重启需重设:slaveof 127.0.0.1 6379
可以将配置增加到文件中。永久生效。

3. 一主二从 shutdown

3.1 一主二从,从节点shutdown

2个从节点原有的数据
在这里插入图片描述

一个从节点shutdown,之后在主节点修改数据
在这里插入图片描述
在这里插入图片描述
重新启动shutdown的从节点
在这里插入图片描述
shutdown后重新启动的从节点变为了独立的主节点
在这里插入图片描述
重新添加到主从集群中
在这里插入图片描述
重新添加到集群中后,发现从节点数据完全从主节点复制过来了

在这里插入图片描述

总结:
  从节点shutdown后,重启不会重新加入到集群中,需要执行slaveof命令,且数据会完全从主节点复制

3.2 一主二从,主节点shutdown

主节点shutdown
在这里插入图片描述
2个从节点,获悉到主节点状态为down,但不会上位
在这里插入图片描述
在这里插入图片描述
主节点重新上线,任然为集群中的主节点
在这里插入图片描述

4. 主从复制原理

  Slave启动成功连接到master后会发送一个sync命令
  Master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令, 在后台进程执行完毕之后,master将传送rdb文件到slave,以完成一次完全同步

全量复制:master 开启一个后台保存进程,以便于生产一个 RDB 文件。同时它开始缓冲所有从客户端接收到的新的写入命令。当后台保存完成时, master 将数据集文件传输给 slave, slave将之保存在磁盘上,然后加载文件到内存。再然后 master 会发送所有缓冲的命令发给 slave。这个过程以指令流的形式完成并且和 Redis 协议本身的格式相同。
增量复制:当一个 master 实例和一个 slave 实例连接正常时, master 会发送一连串的命令流来保持对 slave 的更新,以便于将自身数据集的改变复制给 slave :包括客户端的写入、key 的过期或被逐出等等。

  当 master 和 slave 之间的连接断开之后,因为网络问题或者是主从意识到连接超时, slave 重新连接上 master 并会尝试进行部分重同步:这意味着它会尝试只获取在断开连接期间内丢失的命令流。当无法进行部分重同步时, slave 会请求进行复制。这会涉及到一个更复杂的过程,例如 master 需要创建所有数据的快照,将之发送给 slave ,之后在数据集更改时持续发送命令流到 slave 。

在这里插入图片描述

  每一个 Redis master 都有一个 replication ID :这是一个较大的伪随机字符串,标记了一个给定的数据集。每个 master 也持有一个偏移量,master 将自己产生的复制流发送给 slave 时,发送多少个字节的数据,自身的偏移量就会增加多少,目的是当有新的操作修改自己的数据集时,它可以以此更新 slave 的状态。复制偏移量即使在没有一个 slave 连接到 master 时,也会自增,所以基本上每一对给定的 Replication ID, offset 都会标识一个 master 数据集的确切版本。
  当 slave 连接到 master 时,它们使用 PSYNC 命令来发送它们记录的旧的 master replication ID 和它们至今为止处理的偏移量。通过这种方式, master 能够仅发送 slave 所需的增量部分。但是如果 master 的缓冲区中没有足够的命令积压缓冲记录,或者如果 slave 引用了不再知道的历史记录(replication ID),则会转而进行一个全量重同步:在这种情况下, slave 会得到一个完整的数据集副本,从头开始。

5. 去中心化,slave作为下一个slave的master

  上一个Slave可以是下一个slave的Master,Slave同样可以接收其他 slaves的连接和同步请求,那么该slave作为了链条中下一个的master, 可以有效减轻master的写压力,去中心化降低风险。
在这里插入图片描述

slaveof  <ip><port>

  中途变更转向:会清除之前的数据,重新建立拷贝最新的
风险是一旦某个slave宕机,后面的slave都没法备份;
  主机挂了,从机还是从机,无法写数据

如:
修改从节点,为slave的从节点,6381的主节点为6380
在这里插入图片描述
主节点6379下仅剩下一个slave
在这里插入图片描述

6. 反客为主

当一个master宕机后,后面的slave可以立刻升为master,其后面的slave不用做任何修改。

slaveof  no one 

将从机变为主机
如:
6379下线
在这里插入图片描述
在这里插入图片描述
6380从节点变为主节点
在这里插入图片描述

7. 复制延时

  由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重

<think>我们面临的问题是:尽管在redis.conf和Spring Boot配置中设置了相同的密码,但健康检查仍然返回"AUTH failed"错误。以下将系统性地排查此问题。 参考引用[1]和[2]可知,Redis开启认证后,客户端必须通过AUTH命令提供密码。而引用[3]则说明如果未正确配置,可能会出现安全漏洞(即不需要密码也能操作)。引用[4][5]强调了redis.conf文件的重要性。 我们将从四个层面排查: 1. Redis服务端配置 2. Spring Boot应用配置 3. 网络与连接 4. 健康检查机制 --- ### Redis服务端配置验证 #### 1.1 确认密码实际生效 - 使用redis-cli登录验证: ```bash redis-cli -h your_redis_host -p 6379 127.0.0.1:6379> AUTH your_password # 执行认证[^2] OK # 成功应返回OK ``` 若返回`(error) ERR invalid password`,则服务端密码与预期不符。 #### 1.2 检查redis.conf的requirepass - 在redis.conf中搜索`requirepass`(注意:配置项前**不能**有注释符`#`): ```conf requirepass your_strong_password # 必须为未注释状态[^4][^5] ``` - **常见错误**:多环境配置文件混淆(如开发环境与生产环境配置不同)。 #### 1.3 重启Redis使配置生效 - 修改redis.conf后必须重启Redis: ```bash redis-cli shutdown # 关闭Redis[^2] redis-server /path/to/redis.conf # 重新启动 ``` #### 1.4 检查是否多密码共存 - Redis支持动态设置密码(临时覆盖redis.conf): ```bash 127.0.0.1:6379> CONFIG GET requirepass # 查看运行时密码[^2] 1) "requirepass" 2) "temporary_password" # 若与配置文件不同,说明被动态修改 ``` **解决方案**:通过`CONFIG SET requirepass "your_password"`临时修复,并同步修改redis.conf永久生效。 --- ### 二、Spring Boot应用配置排查 #### 2.1 检查配置优先级 - 确保`application.yml`中密码正确且未被覆盖: ```yaml spring: redis: password: your_strong_password # 注意缩进 ``` - **配置冲突排查**: - 检查是否有多个配置文件(如`application-dev.yml`覆盖了配置) - 检查环境变量(如`SPRING_REDIS_PASSWORD`可能覆盖yml配置) #### 2.2 密码特殊字符处理 - 若密码包含特殊字符(如`@`、`#`、`:`),需进行URL编码: ```yaml spring: redis: password: "%23your%40password" # #your@password 编码后 ``` #### 2.3 连接池配置影响 - 连接池(如Lettuce)可能缓存旧密码连接: ```yaml spring: redis: lettuce: pool: max-active: 8 # 添加以下配置强制验证连接 test-while-idle: true time-between-eviction-runs: 5s ``` 重启应用刷新连接池。 --- ### 三、网络与连接层检查 #### 3.1 确认连接目标正确 - 检查是否连接到正确的Redis实例: ```yaml spring: redis: host: correct_redis_host # 非127.0.0.1(容器环境下常为服务名) port: 6379 ``` #### 3.2 防火墙/安全组规则 - 确保应用服务器能访问Redis的6379端口: ```bash telnet your_redis_host 6379 # 或使用nc ``` 连接失败则需调整防火墙规则。 #### 3.3 代理或中间件干扰 - 若使用Twemproxy、Redis Sentinel等中间件,需确认其密码配置: ```conf # Sentinel示例(sentinel.conf) sentinel auth-pass mymaster your_password ``` --- ### 四、健康检查机制调试 #### 4.1 查看健康检查详情 - 开启Actuator健康详情端点: ```yaml management: endpoint: health: show-details: always ``` 访问`/actuator/health`查看具体错误信息: ```json { "components": { "redis": { "status": "DOWN", "details": { "error": "ERR AUTH <password> called without any password configured for the default user. Are you sure your configuration is correct?" // 典型错误 } } } } ``` #### 4.2 手动注入RedisHealthIndicator - 自定义健康检查逻辑以打印详细错误: ```java @Bean public RedisHealthIndicator redisHealthIndicator(RedisConnectionFactory factory) { return new RedisHealthIndicator(factory) { @Override protected void doHealthCheck(Health.Builder builder) { try { super.doHealthCheck(builder); // 触发检查 } catch (Exception e) { e.printStackTrace(); // 控制台输出堆栈 throw e; } } }; } ``` 从日志中获取底层异常(如`InvalidPasswordException`)。 --- ### 五、终极解决方案:重置Redis密码 若以上步骤无效,可强制重置密码: 1. **临时关闭认证**(仅限内网安全环境): ```bash redis-cli 127.0.0.1:6379> CONFIG SET requirepass "" # 清空密码[^2] ``` 2. **在Spring Boot中移除密码配置**,测试健康检查是否通过。 3. **重新设置密码**: ```bash 127.0.0.1:6379> CONFIG SET requirepass "new_password" 127.0.0.1:6379> CONFIG REWRITE # 持久化到redis.conf[^2] ``` 4. 同步更新Spring Boot配置为新密码。 --- ### 错误排查表 | 现象 | 原因 | 验证方法 | |-------------------------------|-----------------------|------------------------------| | 健康检查报`NOAUTH` | 密码未传入 | 检查`RedisHealthIndicator`日志 | | 连接池返回`Invalid password` | 连接池缓存旧密码 | 重启应用或刷新连接池 | | `CONFIG GET`显示空密码 | 配置未生效 | 重启Redis服务 | | Telnet连通但认证失败 | 特殊字符未编码 | 对密码进行URL编码 | > ⚠️ **安全提示**:生产环境避免使用简单密码,推荐使用Vault等工具动态管理密码。 --- ### 总结排查步骤 1. **服务端**:`redis.conf` → `requirepass`配置 + 重启Redis 2. **客户端**:Spring配置 → 密码特殊字符处理 + 连接池刷新 3. **网络**:Telnet测试端口连通性 4. **健康检查**:Actuator详情 + 自定义HealthIndicator打印日志 通过以上步骤,可解决99%的"AUTH failed"问题。若仍存在异常,需检查Redis版本兼容性(如Redis 6+的ACL机制影响)。 --- §§相关问题§§ 1. Redis 6.0的ACL机制如何影响Spring Boot应用的认证? 2. 如何在Spring Boot中动态更新Redis密码而不重启服务? 3. 使用Kubernetes ConfigMap管理redis.conf时如何避免密码泄露? 4. Redis集群模式下所有节点是否需要相同密码? 5. Lettuce和Jedis客户端在密码认证处理上有何差异?</think>针对 Redis 健康检查返回 "AUTH failed" 错误的问题,即使确认 `redis.conf` 和 `spring.redis.password` 密码致,仍需进行系统性排查。以下是完整的解决方案: --- ### 、核心排查步骤 #### 1. **验证 Redis 服务端实际生效的密码** ```bash # 连接到 Redis 实例 redis-cli -h your_redis_host # 查看运行时生效的密码(需先通过当前密码认证) 127.0.0.1:6379> AUTH current_password # 使用当前配置的密码 OK 127.0.0.1:6379> CONFIG GET requirepass 1) "requirepass" 2) "actual_password_here" # 此处显示实际生效的密码 ``` - **关键点**:若输出与配置不致,说明配置未生效[^2][^4] #### 2. **检查 Redis 配置加载情况** 在 `redis.conf` 中确认: ```conf # 确保以下配置未被注释且路径正确 requirepass your_strong_password # 密码配置项[^4] include /path/to/security.conf # 检查是否被其他文件覆盖 dir /var/lib/redis # 持久化目录(影响配置保存) ``` - **必须操作**:修改后重启 Redis 并检查进程加载的配置文件: ```bash redis-cli shutdown && redis-server /path/to/redis.conf # 指定配置重启[^2] ps aux | grep redis # 确认进程加载的配置文件路径 ``` #### 3. **Spring Boot 配置深度检查** 在 `application.yml` 中: ```yaml spring: redis: password: ${REDIS_PASSWORD:fallback_password} # 检查环境变量覆盖 host: redis-host # 确认非localhost(容器环境常见问题) port: 6379 # 开启Actuator详细错误 management: endpoint: health: show-details: always ``` - **诊断命令**: ```bash curl -s http://localhost:8080/actuator/health | jq .components.redis ``` 观察返回的错误详情(如 `"error": "ERR AUTH called with invalid password"`) --- ### 二、进阶故障场景排查 #### 场景1:**特殊字符密码处理问题** - **问题特征**:密码包含 `@`、`#`、`:` 等字符 - **解决方案**: ```yaml spring: redis: password: "abc@123#" # 必须用双引号包裹 url: "redis://:abc%40123%23@redis-host:6379" # URL编码特殊字符 ``` #### 场景2:**ACL 权限问题(Redis 6.0+)** ```bash # 查看默认用户状态 127.0.0.1:6379> ACL LIST 1) "user default on #5e8848... ~* &* +@all" # 检查密码哈希和权限 ``` - **修复命令**: ```bash ACL SETUSER default >new_password # 重置密码 ACL SETUSER default on +@all ~* # 赋予权限 ``` #### 场景3:**连接池缓存旧密码** 在 `application.yml` 添加连接验证: ```yaml spring: redis: lettuce: pool: test-while-idle: true # 启用空闲连接检测 time-between-eviction-runs: 10s timeout: 500ms # 防止健康检查阻塞 ``` --- ### 三、网络与安全层排查 | 检查项 | 命令/操作 | 修复方案 | |-------------------------|--------------------------------------------------------------------------|------------------------------| | **防火墙规则** | `telnet redis-host 6379` 或 `nc -zv redis-host 6379` | 开放应用服务器到Redis的流量 | | **SELinux 拦截** | `tail -f /var/log/audit/audit.log \| grep redis` | `setsebool -P redis_connect_any 1` | | **代理中间件干扰** | 检查 Sentinel/Twemproxy 的密码配置 | 同步更新代理配置的密码 | | **容器网络隔离** | `docker exec -it app-container curl redis:6379` | 使用容器网络别名连接 | --- ### 四、终极解决方案 若以上步骤无效,执行密码重置流程: 1. **临时关闭密码验证**: ```bash redis-cli 127.0.0.1:6379> CONFIG SET requirepass "" # 清空密码 ``` 2. **验证健康检查通过** 访问 `/actuator/health` 确认 Redis 状态变为 `UP` 3. **重新设置密码**: ```bash 127.0.0.1:6379> CONFIG SET requirepass "new_password" 127.0.0.1:6379> CONFIG REWRITE # 永久保存到redis.conf[^2] ``` 4. **同步更新 Spring Boot 配置**: ```yaml spring: redis: password: new_password ``` --- ### 五、预防措施 1. **配置变更后强制重启**: ```bash # Redis重启 redis-cli shutdown && redis-server /etc/redis.conf # Spring Boot应用重启(连接池重置) systemctl restart your-spring-app ``` 2. **密码管理规范**: ```yaml # 使用配置中心管理密码 spring: redis: password: ${VAULT_REDIS_PASSWORD} ``` 3. **健康检查增强配置**: ```yaml management: health: redis: enabled: true timeout: 1s # 防止健康检查阻塞 ``` > **关键日志位置**: > - Redis日志:`/var/log/redis/redis-server.log`(查找 `Accepted`/`Auth failed`) > - Spring Boot日志:搜索 `RedisHealthIndicator` 相关错误堆栈 通过以上步骤,可系统性解决 Redis 健康检查的 "AUTH failed" 问题。若在生产环境中,建议使用配置中心统管理密码以避免不致问题。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

但行益事莫问前程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值