项目网站的建设有两种模式,wordpress添加主题慢,梧州房源信息网,网站设计怎么做链接Redis#xff1a;分布式 - 主从复制 概念配置主从模式info replicationslave-read-onlytcp-nodelay 命令slaveof 主从结构一主一从一主多从 主从复制流程数据同步命令全量同步部分同步实时同步 节点晋升 概念
Redis的最佳应用#xff0c;还是要在分布式系统中。对于非分布式… Redis分布式 - 主从复制 概念配置主从模式info replicationslave-read-onlytcp-nodelay 命令slaveof 主从结构一主一从一主多从 主从复制流程数据同步命令全量同步部分同步实时同步 节点晋升 概念
Redis的最佳应用还是要在分布式系统中。对于非分布式系统也就是只有一个主机提供服务此时一旦该主机崩溃那么整个服务就崩溃了这称为单点问题。
因此引入分布式系统多个主机共同完成一个服务既能提高服务并发的能力又能避免单点问题就算一个主机崩溃了还有其他主机可以处理服务。
而分布式系统常见的模式为以下三种
主从模式主从 哨兵模式集群模式
主从模式顾名思义就是有主服务器主节点和从属服务器从节点此时从节点的所有数据都要去和主节点同步。那么从节点就要去复制主节点的数据在Redis中从节点复制了主节点的数据后不允许修改确保了数据完全来自于主节点。
这种模式下写入操作都会分配给主节点而所有查询操作都分配给从节点这样就能保证主节点的数据都是最新的从节点通过数据同步完成数据更新。
本博客讲解Redis的主从模式。 配置主从模式
由于大部分人手上都只有一台主机或者云服务器此时想要打造一个分布式系统就需要用一些其他技巧而不是真的在多个主机上部署分布式。
其实在一台主机上是可以允许多个redis-server进程的只要保证每个进程的端口号不同那么就可以有多个redis-server存在。
首先找一个合适的位置创建一个目录用于存放从节点的配置文件 拷贝redis,conf配置文件到当前目录由于我打算创建两个丛节点所以拷贝了两份。
找到port选项
# Accept connections on the specified port, default is 6379 (IANA #815344).
# If port 0 is specified Redis will not listen on a TCP socket.
port 6379默认的端口号是6379此端口号修改为其它端口不要与主节点冲突。
找到daemon选项
# By default Redis does not run as a daemon. Use yes if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
# When Redis is supervised by upstart or systemd, this parameter has no impact.
daemonize yes保证该选项是yes这样Redis才能在后台运行。
修改这两个配置文件后通过以下指令启动
redis-server 配置文件地址启动后通过ps查看可以看到同时有三个Redis在运行 我绑定的三个端口分别是6379、6380、6381。
想要启动不同的客户端只需要通过-p选项指定不同的端口 但是此时三个节点是单独的三个服务还没有构成主从结构。
配置主从需要通过slaveof有以下三种方式
在配置⽂件中加⼊slaveof {masterHost} {masterPort}当Redis启动时生效在 redis-server 启动命令时加⼊ --slaveof {masterHost} {masterPort}直接使⽤redis命令slaveof {masterHost} {masterPort}
此处通过修改配置文件完成主从配置因为其是持久的后两种方式在每车次启动时都要输入额外的命令。
在两个slave.conf的最末尾加上以下内容
# 配置主从复制
slaveof 127.0.0.1 6379再重启两个服务此时两个节点就变成了主节点的从节点了。
要先杀掉两个进行kill -9 PID 随后再通过之前的命令启动
redis-server ./slave1.conf
redis-server ./slave2.conf 通过netstat查看网络情况 可以发现除了三个redis-server还有很多其它的redis网络连接这是因为主从之间要进行数据传输所以要创建额外的网络连接。
测试一下 左侧端口为6379主节点右侧为6380从节点主节点设置key1 111从节点可以get得到但是当从节点试图写入数据发生报错表示不允许修改数据。 info replication
通过指令info replication可以查看主从相关的信息。
主节点6379
127.0.0.1:6379 info replication
# Replication
role:master
connected_slaves:2
slave0:ip127.0.0.1,port6380,stateonline,offset1602971,lag0
slave1:ip127.0.0.1,port6381,stateonline,offset1602971,lag0
master_failover_state:no-failover
master_replid:23006f1139dc753a96d489311987709770f6c36d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1602971
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:551881
repl_backlog_histlen:1051091role表示当前节点为主节点 connected_slaves当前有两个从节点 slave0第一个从节点的相关信息 ip地址port端口state状态offset同步情况多个从节点的该值可能不同因为同步是要时间的lag当前主从节点之间数据传输的延迟 master_replid主节点的专属id offset主节点的数据进度与从节点的offset匹配如果从节点的offset小于主节点说明从节点没有同步完毕数据版本是落后的 repl_backlog_xxx积压缓冲区后续讲解 从节点6380
127.0.0.1:6380 info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_read_repl_offset:1602985
slave_repl_offset:1602985
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:23006f1139dc753a96d489311987709770f6c36d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1602985
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:551895
repl_backlog_histlen:1051091master_xxx主节点的一些信息slave_priority一个优先级如果主节点崩溃了会从新选主节点与该优先级有关master_replid主节点的id
这些内容也不需要记忆可以去官网查询官方文档有很详细的解释。 slave-read-only
默认情况下从节点只能读取数据。其实从节点也可以通过配置文件修改的只需要把slave-read-onlyno此时从节点就可以修改数据。但是要注意的是从节点修改的数据是不会同步给主节点的这就会导致主从的数据不一致所以不要修改这个配置文件。 tcp-nodelay
Redis主从之间是通过TCP连接完成数据的同步的在TCP内部有一个nagel算法它是一种捎带应答机制的实现。如果启用了该选项那么TCP的延迟就会变高但是消耗的带宽会降低。
而主从之间有时候需要高频同步数据这就对TCP延迟有很高的要求如果延迟太大主从数据不一致查询时就很有可能得到过期的数据。那么此时就可以通过设置tcp-nodelay关闭这个nagel算法这样虽然带宽增加了但是延迟就会降低。
这两种方式传输没有好坏之分而是根据场景需求如果网络环境比较复杂消耗带宽太高就很容易丢包这就得不偿失了。比如在同一个机房内部署的服务器那么此时网络就很简单建议关闭这个nagel算法。但是如果是跨越很远的数据传输比如说在好几个地域布置了机房构建了一个跨越全国甚至全球的分布式系统此时还是开启这个nagel比较好。 命令
slaveof
slaveof no one用于断开主从关系从节点执行该命令后就不再有主节点了而是自成主节点。
示例 从节点6380执行slaveof no one后再次info replicationrole:master说明此时自己已经是主节点了不再从属其他节点。要注意的是从节点变成主节点后原先的数据不会丢失可以继续操作原先的数据。
slaveof用于设置当前节点为其它节点的主节点。
语法
slaveof ip port 示例 此处通过slaveof重新将6379设置为了6380的主节点。
不论是salveof还是slaveof no one都是临时修改主从关系一旦服务重启仍然依照配置文件设置主从关系。 主从结构
在Redis中有很多种主从的组织方式它们构成了不同的拓扑结构。
一主一从
最简单的主从结构自然是一主一从如下 这种结构的功能一般是为了防止单点问题如果主节点崩溃此时从节点立刻代替主节点完成服务。当写命令并发量较高时从节点上开始AOF持久化方式但是主节点只使用RDB方式。这样从节点就代替主节点完成持久化而主节点可以空出更多的资源来完成写入操作。
但是这种方式要关闭主节点的自动重启功能因为主节点使用RDB持久化此时数据往往不是最新的。一旦主节点重启那么就会通过RDB恢复数据导致主节点得到旧数据。而这个旧数据又会同步给从节点此时从节点的AOF新数据就被旧数据覆盖了这就很坑了。 一主多从
实际上数据库的查询操作频率是远大于插入操作的所以一主多从往往是更常见的选择让多个从节点完成读取数据的任务来提高并发能力。
星形结构 这种情况下往往还需要一个负载均衡器来分发读取的流量到多个从节点上让多个从节点接收差不多的访问量。
但是这就会导致主节点要同时与好几个从节点进行数据同步那么主节点的网络压力会很大因此又出现了以下的树形结构。
树形结构 这种结构下主节点只需要与少量的从节点进行同步而其它节点作为从节点的从节点完成二次同步。这样就可以有效减少主节点的网络压力但是这种情况下数据的同步时间会变长因为要经过多层的同步。
树形结构和星形结构也是各有优劣如果希望降低同步的时延不怕主节点承担太多网络压力就用星形结构。如果希望主节点的网络压力得到缓解可以牺牲一部分同步时延那么使用树形结构。 主从复制流程
接下来看一下主从关系是如何建立的流程如下
保存主节点信息
保存主节点的ip、port等信息
建立主从TCP连接
从节点内部通过每秒运行的定时任务维护复制相关逻辑当定时任务发现存在新的主节点后会尝试与主节点建立基于TCP 的网络连接。如果从节点无法建立连接定时任务会无限重试直到连接成功或者用户停止主从复制。
从节点发送ping命令
连接建立成功之后从节点通过 ping命令确认主节点在应用层上是工作良好的。
权限验证
如果主节点设置了requirepass 参数则需要密码验证从节点通过配置 masterauth参数来设置密码。如果验证失败则从节点的复制将会停止。
同步数据集
对于首次建立复制的场景主节点会把当前持有的所有数据全部发送给从节点这步操作基本是耗时最长的所以又划分称两种情况全量同步和部分同步
命令持续复制
当从节点复制了主节点的所有数据之后针对之后的修改命令主节点会持续的把命令发送给从节点从节点执行修改命令保证主从数据的一致性。
接下来详细讲解一下到底Redis是如何完成第56步骤中数据的同步的。 数据同步命令
Redis中提供了一个命令psync其可以完成主从之间的数据同步过程。
语法
psync replcationid offset这两个参数需要进行简单的讲解。
replication id
replid称为复制ID每次主节点重启或者从节点晋升为主节点都会生成一个replid当从节点与主节点建立连接后从节点就可以得到主节点的replid。
通过info replication可以查询到以下内容
master_replid:23006f1139dc753a96d489311987709770f6c36d
master_replid2:0000000000000000000000000000000000000000第一个master_replid就记录着主节点的replid那么master_replid2的作用是什么
有的时候主节点网络不好从节点会误判主节点下线此时从节点就会晋升为主节点也会生成自己的replid。此处的master_replid2会把之前的主节点的replid记录下来。
等到主节点网络恢复后重新与从节点建立连接此时从节点不知道主节点是重启了还是网络恢复了。就会拿master_replid2与主节点的replid对比如果相同说明主节点没有重启只是网络出问题了此时从节点会重新认主。如果不同那么就是主节点下线了。
offset
offset称为偏移量其用于维护节点的数据进度每当主节点写入数据后都会把命令的字节长度进行累加记录到offset中。也就是说随着数据的写入这个值会越来越大。
而从节点每次更新数据也会增加自己的偏移量表示自己同步的进度。当从节点的偏移量和主节点的偏移量完全相同那么说明从节点已经同步到主节点的所有数据了。 replid 和 offset 共同确定一个唯一的数据集 只要 replid 和 offset 相同那么两个节点上的所有数据完全相同。
psync replcationid offset如果 offset 为-1那么此时进行全量复制将所有的数据都复制一份到从节点。如果offset为具体的一个偏移量那么从节点将从偏移量开始往后的所有数据都复制过来。
如果psync不传入任何参数那么replid offset默认为? 和-1表示从节点不知道主节点的replid和offset。
但是不论从饥饿点发送什么命令如果主节点过于繁忙那么此时不一定会执行从节点预期的复制方式。比如从节点申请进行全量复制此时主节点无法承受这么多网络压力那么可能就会变成部分复制。
当输入psync后可能得到以下三种结果
FULLRSYNC replid offset进行全量复制CONTINUE进行部分复制-ERR说明主节点不支持psync此时可以使用sync
此处sync是在前台运行的命令一旦执行sync主节点的所有命令都会被阻塞。 全量同步
全量复制是 Redis 最早支持的复制方式主从第一次建立复制时必须进行一次全量复制。
全量复制流程图如下 从节点发送 psync命令给主节点进行数据同步由于是第一次进行复制从节点没有主节点的运行 ID 和复制偏移量所以发送 psync ? -1。主节点根据命令解析出要进行全量复制回复FULLRESYNC响应。从节点接收主节点的运行信息进行保存比如主节点的replid。主节点执行 bgsave 进行 RDB 文件的持久化。这一步与第三步同时进行就算主节点已经有RDB文件了但是由于RDB的数据进度是比较落后的所以还是要重新生成一个。主节点发送 RDB 文件给从节点从节点保存 RDB数据到本地硬盘。主节点将从生成 RDB 到接收完成期间执行的写命令写入缓冲区中等从节点保存完 RDB 文件后主节点再将缓冲区内的数据补发给从节点补发的数据仍然按照RDB的二进制格式追加写入到收到的 RDB文件中保持主从一致性。从节点清空自身原有旧数据。从节点加载 RDB 文件得到与主节点一致的数据。如果从节点加载 RDB完成之后开启了 AOF持久化功能它会进行bgrewrite 重写操作因为上面这个过程从节点收到了大量数据此时AOF也在同步记录数据此时进行一次重写对刚才收到的数据进行一个压缩。
无硬盘模式
新版的Redis对以上过程又做了优化主节点在生成RDB文件时要把数据写入文件然后再把文件传输给从节点。而无硬盘模式下主节点生成了RDB格式的数据后不会写入文件而是直接发送给从节点。这样就减少了大量硬盘IO提高了同步效率。
从节点也相同之前的从节点会把收到的RDB数据存储到硬盘生成文件然后再加载文件。无硬盘模式下从节点直接加载网络中的RDB数据不再写入硬盘。 部分同步
部分复制主要是 Redis 针对全量复制的过高开销做出的一种优化措施使用 psync replicationld offset 命令实现。当从节点正在复制主节点时如果出现网络闪断或者命令丢失等异常情况时从节点会向主节点要求补发丢失的命令数据如果主节点的复制积压缓冲区存在数据则直接发送给从节点这样就可以保持主从节点复制的一致性。补发的这部分数据一般远远小于全量数据所以开销很小。
部分复制流程如图所示 当主从节点之间出现网络中断时如果超过repl-timeout 时间主节点会认为从节点故障并中断复制连接。主从连接中断期间主节点依然响应命令但这些复制命令都因网络中断无法及时发送给从节点所以暂时将这些命令滞留在复制积压缓冲区中。当主从节点网络恢复后从节点再次连上主节点。从节点将之前保存的 replicationld 和 offset 作为 psync 的参数发送给主节点请求进行部分复制。主节点接到 psync 请求后进行必要的验证。随后根据 offset 去复制积压缓冲区查找合适的数据并响应 CONTINUE 给从节点。主节点将需要从节点同步的数据发送给从节点最终完成一致性。 实时同步
主从节点在建立复制连接后主节点会把自己收到的修改操作通过 TCP 长连接的方式源源不断的传输给从节点从节点就会根据这些请求来同时修改自身的数据从而保持和主节点数据的一致性。
另外这样的长连接需要通过心跳包的方式来维护连接状态(这里的心跳是指应用层自己实现的心跳而不是 TCP 自带的心跳)。
主从节点彼此都有心跳检测机制各自模拟成对方的客户端进行通信。主节点默认每隔 10 秒对从节点发送 ping命令判断从节点的存活性和连接状态。从节点默认每隔1秒向主节点发送 replconfack{offset}命令给主节点上报自身当前的复制偏移重。
如果主节点发现从节点通信延迟超过repl-timeout配置的值(默认60秒)则判定从节点下线断开复制客户端连接。从节点恢复连接后心跳机制继续进行。 那么以上三种同步机制和主从复制有什么关系在整个主从同步的过程中最后两步分别是同步数据集和持续复制命令。
同步数据集 如果是第一次同步触发全量同步如果是断线重连触发部分同步 持续复制命令 进行实时同步 节点晋升
先前提及过很多次从节点是可以晋升为主节点的那么什么时候从节点会晋升
这分情况对于一般的主从复制情况如下
主动断开主从关系
用户可以通过slaveof no one命令断开与主节点的连接此时从节点断开连接后自动晋升为主节点。
主节点崩溃
在一般的主从情况下如果主节点崩溃此时从节点不会自动晋升需要用户进行手动操作。这是一个非常难办的问题因为服务器崩溃是不可预知的如果大半夜服务崩溃了此时程序员又不能及时重启就会造成很大麻烦。后续Redis引入了哨兵机制处理这种情况下的自动晋升。