1. 了解redis的 主从切换吗?
Redis 的主从切换是保障集群高可用性的核心机制,用于在主节点故障或需要维护时,将从节点提升为新主节点,确保服务持续可用。其切换过程可分为自动切换 (由哨兵 Sentinel 主导)和手动切换(运维操作),具体流程和关键细节如下:
一、自动切换(基于哨兵 Sentinel)
哨兵是 Redis 官方提供的高可用解决方案,通过监控主从节点状态、自动判断故障并执行切换,核心流程如下:
1. 故障检测(判断主节点是否下线)
- 主观下线(SDOWN) :单个哨兵通过
PING命令检测主节点,若超过down-after-milliseconds阈值(默认 30 秒)未收到有效响应(PONG),则标记主节点为 "主观下线"。 - 客观下线(ODOWN) :当多个哨兵(数量由
quorum参数指定,如 3 个哨兵需 2 个同意)都认为主节点主观下线时,通过投票机制确认主节点 "客观下线",触发切换流程。
2. 从节点筛选(选择最优从节点)
哨兵从所有健康的从节点中,筛选出适合晋升为主节点的候选者,筛选规则:
- 网络可用性 :排除与主节点断开连接过久的从节点(通过
repl-timeout判断)。 - 数据完整性:优先选择复制偏移量最大的从节点(数据与原主节点最接近)。
- 优先级 :通过
slave-priority配置指定优先级(值越小优先级越高,默认为 100),优先级高的从节点优先被选中。 - 运行状态 :排除处于
down状态或正在同步的从节点。
3. 执行切换(提升从节点为主节点)
- 哨兵向选中的从节点发送
SLAVEOF NO ONE命令,使其停止复制原主节点,成为新主节点。 - 哨兵向其他从节点发送
SLAVEOF <新主节点IP> <端口>命令,让它们改为复制新主节点。 - 哨兵更新内部配置,记录新主节点信息,并通过发布订阅机制(
__sentinel__:hello频道)通知客户端新的主节点地址。
4. 原主节点恢复后的处理
若原主节点故障恢复,哨兵会将其降级为从节点,让它复制新主节点的数据,避免双主冲突。
二、手动切换(运维干预)
在某些场景(如主节点升级、负载均衡)下,需手动触发主从切换,常用方式:
-
SLAVEOF NO ONE+SLAVEOF命令- 在目标从节点执行
SLAVEOF NO ONE,使其成为独立主节点。 - 在其他从节点执行
SLAVEOF <新主节点IP> <端口>,让它们同步新主节点。 - 在原主节点执行
SLAVEOF <新主节点IP> <端口>,使其降级为从节点。
- 在目标从节点执行
-
使用
redis-cli工具 部分 Redis 集群管理工具(如redis-trib.rb)或第三方工具(如 Codis)提供了一键切换命令,简化操作。 -
注意事项
- 切换前需确保从节点数据已同步完成(通过
INFO replication查看master_repl_offset与主节点一致)。 - 切换期间可能存在短暂的读写不一致,需业务层做好兼容(如重试机制)。
- 切换前需确保从节点数据已同步完成(通过
三、主从切换的潜在问题与解决
-
数据丢失风险
- 问题:主节点故障时,若有未同步到从节点的写命令(如主节点刚接收写请求但未传播给从节点就宕机),切换后会丢失数据。
- 解决 :
- 开启主节点持久化(AOF/RDB),避免重启后数据丢失。
- 配置
min-replicas-to-write和min-replicas-max-lag,要求主节点至少有 N 个从节点在指定时间内完成同步,否则拒绝写请求。
-
脑裂问题
- 问题:主节点与哨兵网络隔离(但自身正常),哨兵误认为主节点宕机并提升新主节点,导致原主节点和新主节点同时存在,客户端可能连接到原主节点写入数据,后续原主节点降级为从节点时,这部分数据会被覆盖。
- 解决 :
- 配置
min-replicas-to-write,确保主节点只有在足够多从节点连接时才接受写请求,隔离期间因不满足条件而拒绝写入。 - 监控节点网络状态,及时发现并处理脑裂。
- 配置
-
切换期间的服务不可用
- 问题:自动切换需经历故障检测、筛选、晋升等过程(通常几秒到十几秒),期间客户端可能无法正常读写。
- 解决 :
- 客户端实现重试机制,切换完成后自动连接新主节点(通过哨兵提供的
sentinel get-master-addr-by-name命令获取新主节点地址)。 - 合理配置哨兵参数(如减小
down-after-milliseconds),缩短检测和切换时间。
- 客户端实现重试机制,切换完成后自动连接新主节点(通过哨兵提供的
四、总结
Redis 主从切换的核心是 **"故障检测→候选筛选→角色转换→集群同步"**,自动切换依赖哨兵实现高可用,手动切换用于可控运维场景。实际使用中需关注数据一致性、脑裂风险和切换期间的服务连续性,通过合理配置和客户端适配,确保切换过程平稳可靠。
2. 了解redis的主从复制吗?
Redis 的主从复制(Master-Slave Replication)是实现数据备份、读写分离和高可用的核心机制,通过将主节点(Master)的数据同步到从节点(Slave),保证从节点数据与主节点一致。其核心原理是 **"主节点记录写操作,从节点复制并执行这些操作"**,具体实现和流程如下:
一、主从复制的核心作用
- 数据备份:从节点作为主节点的副本,避免单节点数据丢失风险。
- 读写分离:主节点负责写操作,从节点负责读操作,分担主节点压力。
- 高可用基础:当主节点故障时,从节点可通过主从切换成为新主节点,保证服务持续可用。
二、主从复制的实现流程
主从复制的完整过程分为初始化阶段(全量同步) 和运行阶段(增量同步),具体步骤如下:
1. 建立连接(从节点发起)
- 从节点通过
SLAVEOF <master-ip> <master-port>命令指定主节点地址,发起复制请求。 - 从节点与主节点建立 TCP 连接,随后发送
PING命令确认连接有效性,主节点返回PONG响应。 - 若主节点设置了密码(
requirepass),从节点需通过AUTH <password>命令认证,否则复制失败。
2. 全量同步(首次连接或数据差异大时)
当从节点首次连接主节点,或主节点的历史命令已超出从节点所需范围(如从节点离线过久),会触发全量同步,将主节点的完整数据同步到从节点:
- 步骤 1:主节点生成 RDB 快照 主节点收到复制请求后,执行
bgsave命令异步生成当前数据的 RDB 快照,并将生成期间的新写命令记录到复制缓冲区(Replication Buffer)。 - 步骤 2:主节点发送 RDB 快照RDB 生成完成后,主节点将快照文件发送给从节点。从节点接收完成后,清空本地数据,加载 RDB 恢复初始数据(此过程从节点会阻塞,无法处理请求)。
- 步骤 3:主节点发送缓冲命令RDB 同步完成后,主节点将复制缓冲区中记录的 "生成 RDB 期间的新命令" 发送给从节点,从节点执行这些命令,最终与主节点数据一致。
3. 增量同步(正常运行时)
全量同步完成后,主从节点进入增量同步阶段,实时保持数据一致:
- 主节点每执行一次写命令(如
SET、HSET),都会将命令同步到复制积压缓冲区(Replication Backlog Buffer) ,并更新自身的复制偏移量(Offset)。 - 从节点通过 TCP 连接接收主节点的命令流,执行后更新自己的复制偏移量,确保与主节点偏移量一致。
- 从节点会定期向主节点发送
REPLCONF ACK <offset>命令,报告自己的当前偏移量,主节点通过对比偏移量判断是否需要补传命令。
4. 断线重连与部分同步(Redis 2.8+)
从节点若因网络波动断线,重连后无需再次全量同步,而是通过部分同步快速恢复:
- 主节点维护一个复制积压缓冲区 (环形队列,默认 1MB,可通过
repl-backlog-size配置),缓存最近的写命令及对应偏移量。 - 从节点重连后,发送自己的偏移量给主节点。若主节点的缓冲区包含该偏移量之后的命令,则仅发送这部分命令(增量同步);否则触发全量同步。
三、主从复制的核心配置
| 配置参数 | 作用说明 |
|---|---|
slaveof <ip> <port> |
从节点指定主节点地址(永久生效需配置在 redis.conf 中)。 |
replica-read-only yes |
从节点设为只读模式(默认开启,避免从节点误写数据)。 |
slave-priority 100 |
从节点优先级(主从切换时,值越小越优先被选为新主节点)。 |
repl-backlog-size 1mb |
复制积压缓冲区大小(越大,支持从节点断线后重连的时间窗口越长)。 |
repl-timeout 60 |
复制超时时间(超过此时间未收到数据,视为同步失败)。 |
min-replicas-to-write 1 |
主节点至少需要 1 个从节点保持连接,否则拒绝写请求(防止脑裂数据丢失)。 |
四、主从复制的潜在问题与解决
-
全量同步开销大
- 问题:RDB 生成和传输会占用主节点 CPU、内存和带宽,从节点加载 RDB 时会阻塞。
- 解决:避免频繁全量同步(增大
repl-backlog-size);在低峰期执行主从切换;使用无盘复制(repl-diskless-sync yes,主节点直接通过网络发送 RDB 给从节点,不写入磁盘)。
-
数据延迟
- 问题:主节点写命令同步到从节点存在延迟,可能导致读写分离时从节点返回旧数据。
- 解决:优化网络环境;减少主节点写压力;业务层容忍短期不一致或通过
WAIT命令强制等待从节点同步(WAIT 1 5000表示等待至少 1 个从节点同步,超时 5000ms)。
-
主节点单点风险
- 问题:主节点故障会导致写服务中断,需手动切换。
- 解决:结合哨兵(Sentinel)实现自动主从切换,或使用 Redis Cluster 集群。
总结
Redis 主从复制通过 **"全量同步初始化 + 增量同步实时更新"** 的机制,实现了主从节点数据一致,是读写分离和高可用的基础。其核心依赖 RDB 快照、复制缓冲区、偏移量追踪等技术,通过合理配置可平衡同步效率与系统开销,满足不同业务场景的需求。
3. 场景设计: 如何用redis实现一个简化版的关系型数据库(类似MySQL),不考虑事务的情况下?
4. 场景设计: 如何设计用redis存储类似MySQL的索引?如何根据一个索引的uuid去查询它关联的所有主键id的行记录?如何在进行select * 操作去查询完联合索引后,如何利用redis进行回表查询其他字段数据?
5. 算法设计: 给定一个字符串,我们需要找到它长度最长的一个严格递增子序列,你该如何设计? (注: 我们递增按照字典顺序进行排序,子序列
6. 最近有没有看到过什么有意思的技术?
7. 最近刚出的Java21有了解过吗?(新特性)
Java 21 于 2023 年 9 月 19 日发布,是一个长期支持(LTS)版本,它引入了许多新特性来提升开发效率、增强性能和优化编程体验。以下是一些核心新特性:
- 虚拟线程(Virtual Threads):通过 M:N 调度模型,将轻量级的虚拟线程映射到少量的操作系统线程上,实现高并发。虚拟线程单线程内存占用仅 400 字节,相比传统线程的 1MB+,大大降低了资源消耗,支持百万级并发任务,适用于 I/O 密集型服务。
- 模式匹配(Pattern Matching) :进一步增强了模式匹配功能,包括
Switch模式匹配和instanceof模式匹配。Switch模式匹配可以减少冗余的类型检查,使代码更加简洁,支持嵌套解构;instanceof模式匹配允许在条件判断中直接解构变量,方便后续使用。 - 记录模式(Record Patterns) :是对记录类型的扩展,简化了不可变数据对象的处理逻辑。它允许将记录模式与
instanceof等操作结合使用,更方便地访问和操作记录类的组件,增强了代码的可读性。 - 字符串模板(String Templates) :提供了一种更简洁、安全的方式来动态构建字符串。通过使用占位符
${},可以将变量的值直接嵌入到字符串中,还支持自定义模板处理器,防止 SQL 注入等安全问题,同时也支持多行文本块。 - 结构化并发(Structured Concurrency) :通过
StructuredTaskScope等机制,将多个相关任务组织成一个逻辑单元,当一个任务完成或失败时,其他相关任务可以被正确地管理和处理,解决了线程泄漏和任务取消延迟问题,使并发编程更加可靠和易于理解。 - 分代 ZGC(Generational ZGC):是对 ZGC 垃圾回收器的进一步优化,将堆内存分为年轻代和老年代,分别管理不同生命周期的对象,通过更频繁地收集年轻对象,提高了垃圾回收效率,最大停顿时间优化至亚毫秒级,提升了应用程序的性能和稳定性。
- 向量 API(Vector API):在 Java 21 中成为正式版,它提供了一种高效的方式来进行向量计算,利用 SIMD(单指令多数据)指令加速数值计算,性能相比传统方式可提升 5-10 倍,适用于科学计算、数据分析等领域。
- 未命名类和实例 main 方法(Unnamed Classes and Instance Main Methods):允许在不定义命名类的情况下编写简单的程序,直接在方法中编写代码,使代码更加简洁,适合快速原型开发和小型脚本编写。