尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Redis主从配置详解:从原理到实操,彻底搞定复制与高可用

Redis主从配置详解:从原理到实操,彻底搞定复制与高可用 搞技术的人应该都遇过这种场面服务端联调得好好的一上线生产环境十几个实例同时连一个 Redis某天半夜主节点内存爆了直接宕机所有读写请求全堆在超时里值班电话被打爆。事后我们复盘根本问题不是 Redis 不够快而是整个架构里只有一个单点。后来我们把 Redis 改成标准的主从配置一台主节点负责写两台从节点分担读再配合哨兵做自动切换这个坑才算彻底填平。这篇就聊聊 Redis 主从配置这件事。它不是什么新东西但是大部分人刚接触时要么只知道replicaof这一条命令要么就是从网上抄一段配置就跑完全不知道主从复制背后发生了什么。我会把原理、实操、验证、排障一次说清楚适合刚入门的同学照着搭也适合已经配过但没细想过为什么的运维大哥随便翻翻。1. 为什么需要 Redis 主从配置1.1 单机 Redis 的典型瓶颈很多人觉得 Redis 快一台就能扛住所有业务这个说法在开发环境、小流量场景下没错但一旦到了线上单机 Redis 会有三个绕不开的问题。第一个是单点故障。Redis 本身是内存数据库数据全在内存里进程一挂没落盘的缓存数据说没就没。即使开了 RDB 和 AOF 持久化恢复也需要时间而这期间服务完全不可用。第二个是读写压力。单机 Redis 的瓶颈往往是网络带宽和单线程 CPU把读写都压到一台机器上QPS 到一定量级就开始抖动。第三个是运维窗口。比如要做版本升级、持久化文件重写、机器迁移单机模式只能停机业务受到直接影响。这三件事叠加起来单机 Redis 就像一个人同时当客服、做账、守仓库白天还能顶一顶半夜一个喷嚏把服务器吓宕机全公司都跟着加班。1.2 主从复制能解决什么Redis 的主从复制核心思路是维护多份相同的数据副本一个主节点master接受写操作一个或多个从节点slave/replica把主节点的数据实时复制过来对外分担读操作。用生活化的例子理解主节点像公司总账本从节点是各门店的抄本。总账本上每写一笔抄本也跟着抄一笔。平时客户查账去就近的抄本看只有改账才到总账本那边去。这么做的好处非常直观读写分离写请求只走主节点读请求可以分散到多个从节点整体吞吐量立刻提升。数据热备份主节点宕了从节点手里还有一份完整数据不会出现“整个缓存全丢”的惨案。为高可用打基础配合哨兵或集群从节点可以自动提升为新主节点业务无感知。我见过不少团队一上来就搞 Redis Cluster结果发现还不会走就想跑。主从配置是 Redis 高可用体系的底座先把这一层玩明白后面搞哨兵、搞集群都会顺手很多。2. 主从复制背后的原理2.1 数据是如何从主节点到从节点的光会配replicaof不算懂主从至少要搞清楚复制过程分几个阶段。建立主从关系后从节点会向主节点发送同步请求。主节点收到请求会执行一次BGSAVE生成 RDB 快照文件同时把快照生成期间收到的所有写命令缓存到复制缓冲区内。快照生成完主节点把 RDB 文件传给从节点从节点加载完文件后主节点再把缓冲区里积攒的写命令发给从节点。这只是全量同步阶段。之后主节点会持续地把每条写命令以命令流的形式推送给从节点这个过程叫增量同步也叫命令传播。从节点怎么保证自己不丢命令靠的是复制偏移量replication offset。主节点和从节点各自维护一个偏移量主节点每发送 N 字节数据自己偏移量加 N从节点每接收并应用 N 字节自己的偏移量也加 N。当两者偏移量一致说明数据同步到位如果不一致从节点会主动要求主节点补发缺失的数据。2.2 为什么大多数场景选异步复制Redis 默认是异步复制意思是主节点执行完写命令后立刻返回结果给客户端同时异步把命令发给从节点不等从节点确认。Argon2 选异步复制还是同步复制本质是性能和数据安全之间的取舍。异步复制延迟极低对主节点性能几乎没有影响代价是极端情况下主节点宕机时可能有极少量的写命令还没来得及同步到从节点导致从节点数据比主节点少那么一丁点。很多业务其实能容忍这种“秒级甚至毫秒级的数据不一致”。比如热点数据缓存丢了可以回源数据库重建比如验证码稍微延迟一点也能接受。对一致性要求极高的场景比如库存扣减就别只靠 Redis 主从得在应用层加额外校验。所以实际项目里绝大多数人还是采用默认的异步复制再用哨兵和备份策略兜底。从节点默认是只读的replica-read-only yes就是干这个用的。这么做是为了防止误操作把从节点数据写脏导致主从数据不一致。如果确实有极端情况需要在从节点上临时执行写命令也要记得事后清理不然后患无穷。3. 环境准备与 Redis 安装3.1 下载和安装动手之前先把环境准备好。Redis 官网能下到最新稳定版源码包Linux 下编译安装挺简单。下载 tar.gz 包后解压进入目录执行make编译完成后再执行make install二进制文件会装到/usr/local/bin下面。wget https://download.redis.io/releases/redis-7.2.4.tar.gz tar xzf redis-7.2.4.tar.gz cd redis-7.2.4 make make install编译的时候如果报错缺少 gcc先执行yum install gcc或apt-get install build-essential。Windows 下没有官方原版 Redis 的二进制包常见做法是装一台 Linux 虚拟机或者用 Docker 直接拉镜像跑。比如docker pull redis:7.2然后分别映射 6379、6380、6381 三个端口这样一台机器上能模拟出三个实例适合学习主从配置。3.2 最小配置模板Redis 默认只允许本机访问做实验前先得把网络层放开。这里给出一个基础配置模板用的参数我会逐个解释。# 允许任意 IP 连接生产环境请改成实际内网网段 bind 0.0.0.0 # 关闭保护模式 protected-mode no # 后台运行 daemonize yes # 日志文件 logfile redis.log # 数据目录 dir /data/redis # 开启持久化生产环境通常 RDB 和 AOF 都开 save 900 1 save 300 10 save 60 10000 appendonly yesbind 0.0.0.0是让 Redis 监听所有网卡的请求实验环境方便但生产环境千万不要这么写要让主从节点通过内网互通暴露公网基本等于引狼入室。protected-mode no和bind配合使用否则 Redis 会拒绝非本机连接。save后面跟的是触发 RDB 的条件比如save 300 10表示 300 秒内至少有 10 次写操作就生成一次快照。4. 主从配置实操步骤4.1 准备三个实例一主两从我习惯在一台机器上开三个进程来演示真实环境里通常分散到三台机器。道理都一样关键是端口要区分开。我建了三个目录分别用于主节点和两个从节点/data/redis/6379/ /data/redis/6380/ /data/redis/6381/每个目录里放一份 redis.conf端口分别设置成 6379、6380、6381。启动命令很简单redis-server /data/redis/6379/redis.conf redis-server /data/redis/6380/redis.conf redis-server /data/redis/6381/redis.conf启动后用redis-cli -p 6379 ping分别测一下三个端口都返回 PONG说明进程起来了。4.2 配置从节点replicaof 的两种方式配置从节点有两种方法效果一样但应用场景不同。第一种是改配置文件。在 6380 和 6381 的配置文件里加上一行replicaof 127.0.0.1 6379注意replicaof后面先写主节点 IP再写主节点端口顺序写反了同步就建立不起来。加完这行后重启 6380、6381 两个实例它们会自动向主节点发起同步。第二种是命令行方式适用于不想重启进程的临时调整redis-cli -p 6380 replicaof 127.0.0.1 6379 redis-cli -p 6381 replicaof 127.0.0.1 6379这种方法的好处是立即生效适合在线上快速把某个从节点提升成主节点或者给新扩容的节点指定主节点。但要注意命令方式不写进配置文件实例重启后配置就丢了。所以长期维护的节点我建议配置文件和命令配合着用重启前先确认命令已经写回配置文件。4.3 启动与连接验证配置完最关心的就是到底同步上没有。看主节点日志会有一段类似的内容Synchronization with replica 127.0.0.1:6380 succeeded看看从节点日志会有MASTER - REPLICA sync started、Full resync这些字样。同步成功后我来亲自验证一下。先往主节点写几个 keyredis-cli -p 6379 set user:1001 {name:zhang,level:3} redis-cli -p 6379 set user:1002 {name:li,level:5}然后去从节点查redis-cli -p 6380 get user:1001 redis-cli -p 6381 get user:1002能看到同样的数据说明复制链路通了。再试试往从节点写数据redis-cli -p 6380 set forbidden key这时候会报错READONLY You cant write against a read only replica这正是我们想要的行为——从节点保护了自己不会出现脑裂式的数据扰动。4.4 读写分离后应用侧怎么改主从配好后客户端代码也得跟着调整。很多项目一开始只配置了一个 Redis 连接读写都走那个地址。现在要改成写操作走主节点地址读操作轮询或随机走各个从节点地址。以 Java 的 Lettuce 客户端为例可以配置一个读写分离的连接核心思路是设置setReadFrom(ReadFrom.REPLICA)。Python 的 redis-py 里则可以通过redis.Redis(host..., port6379)写redis.Redis(host..., port6380)读。实际编码细节每个语言都不一样但方向是统一的主节点承担写流量从节点承担读流量。这里要特别提醒一下有些业务读多写少比例甚至到 10:1用了主从之后读压力瞬间摊平。但也要小心“读放大”如果从节点配了三五台每台都去主节点拉全量同步主节点同步压力会变大。适当调整repl-backlog-size默认 1MB 在写频繁时不够用我一般会调到 16MB 甚至 32MB减少从节点因为 backlog 被覆盖而被迫重新全量同步的情况。5. 验证、监控与故障处理5.1 用 info replication 检查状态配置完不等于万事大吉必须学会用info replication看复制状态。在主从任意节点执行redis-cli -p 6379 info replication返回的信息就是主从关系的体检报告。我整理了一份常用字段说明字段含义期望值role当前节点角色master 或 slaveconnected_slaves已连接的从节点数量大于等于实际节点数master_link_status与主节点的连接状态upmaster_last_io_seconds_ago距上次与主节点通信多少秒小于 5slave_repl_offset从节点的复制偏移量应接近主节点的偏移量master_repl_offset主节点复制偏移量持续增长看master_repl_offset和slave_repl_offset是判断是否同步的关键。我写脚本监控的时候会定期抓主从两边的偏移量如果差值持续变大说明复制延迟高了要去找原因。5.2 主节点宕机了怎么办主节点宕机时从节点不会自动转正这是很多人最容易误解的一点。Redis 主从本身不具备故障自动切换能力必须有哨兵Sentinel进程来做选举和切换。纯手动的应急方案其实不难。假设 6379 主节点挂了我要临时把 6380 提升成主节点redis-cli -p 6380 replicaof no one这条命令会让 6380 断开主从关系变为独立主节点。然后把 6381 重新指向 6380redis-cli -p 6381 replicaof 127.0.0.1 6380再把客户端的写地址从 6379 改成 6380服务就能恢复。整个过程看着简单但速度太慢的话业务已经受影响所以生产环境一定要用哨兵让哨兵自动完成“发现主节点挂掉、选举从节点、执行replicaof no one、通知客户端”这一套动作。5.3 需要注意的坑主从切换后的数据回切手动或者哨兵切换后原主节点恢复时如果直接重新加入集群会有一个很大的隐患。举个例子6379 是原主节点宕机期间客户端往 6380 写了不少新数据。6379 恢复后如果没有被配置成 6380 的从节点而是继续以主节点身份运行这时候线上就有两个主节点两边数据不一致这就是典型的脑裂。正确的做法是原主节点 6379 恢复后要立刻把它降级为 6380 的从节点redis-cli -p 6379 replicaof 127.0.0.1 6380让它把宕机期间缺失的数据补回来等数据追平后再考虑要不要把它重新提升为主节点。这个动作必须写进应急预案我见过不止一次因为回切顺序搞反导致线上数据大面积错乱。6. 常见问题与排查技巧实录6.1 从节点一直 SYNC 失败新手最容易踩的坑就是连不上主节点。现象是从节点日志里反复出现SYNC with master failed。排查思路要看四层第一层看网络主从节点之间能不能 ping 通服务端口能不能 telnet 通。第二层看 Redis 配置主节点是否设置了bind限制protected-mode是否误开了。第三层看防火墙有些云主机的安全组默认不开内网端口。第四层看认证如果主节点设置了requirepass从节点配置里必须同步加上masterauth字段。这里我踩过一次很冤的坑从节点配置文件里的masterauth写的是旧密码主节点改完密码后没同步更新从节点结果从节点一直连不上日志还显示auth error。后来我养成了习惯凡是改主节点密码第一件事就是把所有从节点的masterauth也跟着改掉并且用脚本定期检查master_link_status是否还是 up。6.2 复制延迟过大如果从节点数据总是比主节点慢先从两个角度查。一是网络带宽是否被打满主从节点如果跨机房专线不稳定延迟会很明显。二是主节点是否在写大量大 key比如一个列表里塞了几百万个元素AOF 重写时会拖慢全量同步。排查的时候可以先看心跳时间master_last_io_seconds_ago如果这个值飘忽不定说明网络有问题。如果偏移量差值持续增长再用redis-cli --bigkeys扫一下主节点看看有没有超大 key。大 key 是主从延迟的老朋友了该拆就拆该限制就要限制别让它留在线上。还有一点很多人不知道如果主节点开 AOF而且刷盘策略是appendfsync everysec写盘压力大的时候也会影响复制数据发送。要权衡一致性还是性能临时可以改成appendfsync no缓解磁盘压力但代价是掉电可能丢多一点数据。6.3 常见问题速查表我把主从配置最常见的几个问题整理成一张速查表方便大家部署时对照问题现象可能原因排查动作从节点连不上主节点bind 限制、防火墙、认证失败telnet测端口、检查 requirepass/masterauth同步迟迟不完成大 key、网络差、磁盘慢查看日志、用 bigkeys 扫描从节点只读报错从节点不允许写确认业务读写分离配置主从偏移量不一致网络拥塞、backlog 太小调大 repl-backlog-size、检查带宽切换后脑裂原主节点未降级为从节点恢复后立即执行 replicaof这些坑基本每个 Redis 主从环境都可能遇到提前把排查路径刻在脑子里真出问题时能少走很多弯路。我用下来的最大感受是主从配置本身不复杂但它是理解 Redis 可靠性的第一步。先把同步原理搞明白再自己动手搭一套一主两从然后尝试手动切换、回切踩过一遍坑之后你对 Redis 的“高可用”三个字才算是真正有底了。后面再去接触哨兵、Cluster会发现很多设计思路都是一脉相承的一个环节吃透了整条线都通了。
返回列表