
文章目录一、Redis集群概述二、Redis多节点的启用1启动的方式2演示3传输延迟三、拓扑结构1一主一从2一主多从3树形主从四、主从结点数据复制的流程原理1流程2psync数据同步概述psync语法主从节点信息介绍判断增量复制还是全量复制的方式3全量复制流程4增量复制流程5实时复制五、哨兵1概述2原理第一步 选举leader第二步 选择主节点一、Redis集群概述在分布式系统中通常会把数据存放到多个副本中并且部署到多个服务器以此来满足故障恢复和负载均衡的需求。Redis也是如此它可以实现多个结点。每个结点可以存储相同的数据。结点集合中又可以分为一个主结点和多个从结点。客户端可以在主节点和从节点读数据但是写数据只能在主结点上写。主节点写入新数据则通过本节要讲的主从复制机制把数据同步给从结点。每个从结点只能有一个主节点而一个主节点可以同时具有多个从结点。复制的数据流是单向的只能由主节点到从节点二、Redis多节点的启用1启动的方式启动多个Redis结点的方式有以下三种在配置文件中加入slaveof {masterHost} {masterPort}随 Redis 启动生效建议使用重启之后仍然生效。在redis-server启动命令时加入--slaveof {masterHost} {masterPort}生效重启后不会生效。直接使用 redis 命令slaveof {masterHost} {masterPort}生效重启后不会生效。2演示接下来我们将 redis.conf 配置文件复制一份 redis-slave.conf并且修改其 daemonize 为 yes。创建一个主节点以及两个从节点为例1 . 创建配置文件创建一个文件夹存储不同redis结点的配置文件把主节点的配置文件复制过来重新起名字即可2. 修改新的配置文件slave1.conf 和slave2.conf配置文件中的端口号改成可用端口号不和其他进程冲突即可daemonize选项改成yes表示后台进程运行。此外配置结点的从属关系slave1和slave2作为6379端口结点的从节点3. 启动三个结点启动后进行配置也需要重新启动准备工作完之后我们在6379主节点插入一个数据发现从节点6380也会收到这说明主节点把数据复制给了从节点。如果从节点想要断开与主节点的连接只需要在从节点中执行slaveof no one即可注意redis如果使用server redis-server start 的命令启动直接kill这个redis结点它会自动启动如果需要关闭这个节点需要使用server redis-server stop命令来结束。如果主节点主动断开与从节点的连接那么从节点之间会通过哨兵机制重新选举出一个从节点作为主节点。可以通过info replication查看从结点复制信息通过 slaveof 命令还可以实现切主操作将当前从节点的数据源切换到另⼀个主节点。执⾏slaveof {newMasterIp} {newMasterPort} 命令即可。切主操作主要流程1断开与旧主节点复制关系。2与新主节点建⽴复制关系。3删除从节点当前所有数据。4从新主节点进⾏复制操作。3传输延迟主从节点之间一般是部署到不同的机房中的因此数据传输的延迟是必须考虑的一个因素。redis给我们提供了一个配置选项repl-disable-tcp-nodelay默认值为no表示开启TCP_NODELAY这里没有打错就是开启no可以理解为延迟发送当关闭时主节点产生的命令数据无论大小都会及时地发送给从节点这样主从之间延迟会变小但增加了网络带宽的消耗。适用于主从之间的网络环境良好的场景如同机房部署。当开启时主节点会合并较小的 TCP 数据包从而节省带宽类似于捎带应答。默认发送时间间隔取决于 Linux 的内核一般默认为 40 毫秒。这种配置节省了带宽但增大主从之间的延迟。适用于主从网络环境复杂的场景如跨机房部署。三、拓扑结构1一主一从最简单的结构⽤于主节点出现宕机时从节点提供故障转移⽀持直接变成主节点Redis-A MasterRedis-B Slave如图所⽰。当应⽤写命令并发量较⾼且需要持久化时可以只在从节上开启 AOF这样既可以保证数据安全性同时也避免了持久化对主节点的性能⼲扰。需要注意的是如果主节点宕机要避免其重启导致数据内容出现过时错误。2一主多从对于读命令大的场场景这种结构非常适合客户端不同都从主节点读取数据可以把客户端的请求流分散给其他的从节点实现负载均衡。3树形主从在一主多从的结构中如果读的请求过大从节点设置过多这对主节点的性能开销也是非常大的。因为他需要把自己的数据复制到多个结点此外还有处理读写请求。树形主从结构通过层级划分把数据复制的压力分摊到了从节点集合中一定程度上降低了主节点的性能开销减少主节点的数据复制传输次数四、主从结点数据复制的流程原理1流程2psync数据同步概述psync命令专门用于主从复制。它可以实现两种复制方式全量复制一般用于初次数据同步早期redis版本只支持这种赋值方式。他会把主节点的全部数据发送给从节点当主节点数据量过大这个操作开销会非常大增量复制用于从节点因为一些特殊情况宕机重启之后只需要让主节点补发部分宕机时的数据遗漏的数据即可。因为只需要补发少量数据因此开销较小。从节点会发送当前从节点的replid 和offset根据这个信息主节点判断进行全量复制FULLRESYNC还是增量复制CONTINEU。遇到非预期情况返回ERR表示拒绝请求。注意redis主节点中有一个全局积压缓冲区。具体进行全量复制还是增量复制取决于这个全局缓冲区数据是否已经达到上线如果达到上线进行全量复制。反之直接通过全局积压缓冲区的数据同步给从节点即可。psync语法psync replicationid offset如果replicationid为 并且offset为-1 那么进行全量复制如果replicationid和offset设置为具体的值那么进行增量复制replicationid用于表示每一个集群由主节点自动生成可以同步给从节点。offset是一串数字用来表示从节点与主节点的同步情况。比如主节点offset100从节点offset50。那么从节点还有50量的数据没有从主节点同步过来。如果主从节点offset一样那么他们俩数据一定是一致的随着新的数据写入主节点主节点的offset也是会增加的主从节点信息介绍通过info replication可以查看主从节点信息的role:slave表示当前 Redis 实例的角色是从节点slave主节点master。master_host:127.0.0.1表示主节点的ip地址master_port:6379主节点的端口号。master_link_status:up主从连接状态。up表示当前从节点与主节点的连接正常。如果是down则表示连接断开。master_last_io_seconds_ago:5距离上次与主节点进行数据交互的时间以秒为单位。这里是5秒说明 5 秒前从节点与主节点有数据交互连接是活跃的。master_sync_in_progress:0是否正在进行主从同步。0表示没有正在进行同步即同步已完成或未启动。如果是1则表示正在进行全量同步。slave_repl_offset:63188从节点的复制偏移量replication offset。主节点和从节点的偏移量应该接近如果差距很大可能表示同步延迟。slave_priority:100从节点的优先级用于故障转移failover。默认值是100。如果主节点宕机优先级更高的从节点值越小更有可能被选为主节点。slave_read_only:1从节点是否为只读模式。1表示从节点是只读的Redis 默认设置不能处理写请求只能处理读请求。connected_slaves:0当前从节点连接的下级从节点数量。这里是0表示这个从节点没有其他从节点连接到它。repl_backlog_active:1复制积压缓冲区replication backlog是否激活。1表示已激活。积压缓冲区用于支持部分重同步partial resync当从节点短暂断开后可以通过缓冲区快速恢复同步而不必进行全量复制减少开销。repl_backlog_size:1048576复制积压缓冲区的大小以字节为单位。这里是1048576字节即 1MB。这是主节点用来存储最近写入操作的缓冲区大小。repl_backlog_first_byte_offset:1积压缓冲区中第一个字节的偏移量。这里是1表示缓冲区从偏移量1开始存储数据。repl_backlog_histlen:63188积压缓冲区中存储的历史数据长度以字节为单位。这里是63188字节说明缓冲区中当前存储了 63188 字节的复制数据。如图master_replid和master_replid2都是用来表示主节点或者说当前所属主节点当从节点认为主节点宕机后从节点会选举出一个新的主节点新的主节点的replid赋值给master_replid旧主节点的replid复制给master_replid2。当旧的主节点恢复后从节点可以感知到进而重新回到原来的主结点的怀抱。secod_repl_offset用法是类似的保存旧结点的数据偏移量。判断增量复制还是全量复制的方式主结点master_repl_offset和父结点slave_repl_offset偏移量越接近那么两者延迟越低数据越一致。master_repl_offsetslave_repl_offset一定成立因为master是主结点。主结点还有一个关键参数repl_backlog_size表示主结点的复制挤压缓冲区总大小若master_repl_offset-slave_repl_offsetmaster_backlog_size那么则需要全量复制因为不一致的数据量以及大于主结点复制挤压缓冲区大小。以上讲到的参数单位都是byte默认大小1mb可以配置一般建议调大master_backlog_size3全量复制流程读取中...从节点发送psync ? -1表示请求全量复制主节点进行判断同意后返回FULLRESYNC响应从节点保存主节点的一些必要信息主节点启动RDB快照使用bgsave命令生成RDB文件在硬盘主节点把这个RDB文件发送给从节点。主节点把创建RDB和发送RDB文件给从节点期间的新数据流存储到了全局积压缓冲区一旦从节点解析完成了RDB文件从节点会把缓冲区的数据一并通过RDB格式发送给从节点以此确保数据一致性。从节点清空自己的RDB文件用于接收新的RDB文件。从节点加载 RDB ⽂件得到与主节点⼀致的数据。如果从节点加载 RDB 完成之后并且开启了 AOF 持久化功能它会进⾏ bgrewrite 操作得到最近的 AOF ⽂件。通过上面流程分析我们可以知道全量复制是一个重量操作主节点需要bgsavefork创建子进程把所有数据写入到硬盘然后把硬盘中的数据网络传输给从节点。因此非必要建议不要进行全量复制。无磁盘复制默认情况下, 进⾏全量复制需要主节点⽣成 RDB ⽂件到主节点的磁盘中, 再把磁盘上的 RDB⽂件通过发送给从节点.Redis 从 2.8.18 版本开始⽀持⽆磁盘复制. 主节点在执⾏ RDB ⽣成流程时, 不会⽣成 RDB ⽂件到磁盘中了, ⽽是直接把⽣成的 RDB 数据通过⽹络发送给从节点. 这样就节省了⼀系列的写硬盘和读硬盘的操作开销4增量复制流程实际上就是部分复制。读取中...在上文我们就已经提到了一个概念叫全局积压缓冲区。全局意思是如果主节点从属的任意一个子节点短暂宕机进行部分复制直接在这个缓冲区拿即可。双向箭头表示主从结点连接断开。连接断开期间一直有新的数据写入到主节点表示从结点宕机恢复主动与主结点连接从节点发送自己的replid和offset给主节点如果主节点判断replid与自己一直并且主节点offset与从节点offset之差没要超过缓冲区存储数据大小返回CONTINUE给从节点主节点把缓冲区部分数据同步给从节点。5实时复制当主从节点数据基本同步后开启实时复制。其大致原理为主从节点开启一个TCP长连接。主节点有数据写入那么就源源不断地把数据发送给从节点。主从节点彼此都有⼼跳检测机制各⾃模拟成对⽅的客⼾端进⾏通信。主节点默认每隔 10 秒对从节点发送 ping 命令判断从节点的存活性和连接状态。从节点默认每隔 1 秒向主节点发送 replconf ack {offset} 命令给主节点上报⾃⾝当前的复制偏移量。注意如果主节点发现从节点通信延迟超过repl-timeout 配置的值默认 60 秒则判定从节点下线断开复制客⼾端连接。从节点恢复连接后⼼跳机制继续进⾏五、哨兵1概述前文中我们提到如果主节点挂了Redis可以采用某些机制在其他从节点中选取一个从节点作为主节点这样做可以保证集群的可靠性避免因为主节点确实导致无法进行写操作。那么它是如何实现的呢 答案就是哨兵机制。实际上这个机制类似于RabbitMQ中的仲裁队列同样采用了数据一致性算法——Raft算法。2原理第一步 选举leader每一个哨兵sentinel都是一个独立的进程不断监视主从节点。如果某个哨兵发现主节点挂了可能是误判这种情况就叫主观下线。当半数哨兵发现主节点挂了这种情况叫客观下线客观下线大概率主节点是真的挂了哨兵集合判主节点客观下线后会在哨兵集合会进行内部选举在多个烧饼中选择出一个leader负责在从节点中选择一个新的主节点。某个哨兵一旦感知到需要进行选举自己的任期会增加并且会立马给自己投上一票然后发送信息给其他哨兵也给自己投上一票倘若别的哨兵没有投票并且当前哨兵任期不大于自己那么别的哨兵也会给当前哨兵投上一票。当某个哨兵票数过半那么他就是leader第二步 选择主节点leader根据当前可用从节点按照以下优先级选择主节点根据从节点中的参数slave_priority进行选择选择最大值的为主节点如果slave_priority相同根据offset选择选择slave_priority最大的保证数据最新如果以上条件都相同那么就通过runId进行选择runId每个节点重启后都不一样因此就是随机选择关于raft一致性算法详细可以查看Raft共识算法动画演示完