Redis基础知识(学习笔记18--主从集群)
一.主从相关的配置
1.1 masterauth
# If the master is password protected (using the "requirepass" configuration # directive below) it is possible to tell the replica to authenticate before # starting the replication synchronization process, otherwise the master will # refuse the replica request. # # masterauth <master-password> #
因为我们要搭建主从集群,且每个主机都有可能会是Master,如果设置验证属性requirepass。一定要每个主机的密码都设置为相同的。此时每个配置文件中都要设置两个完全相同的属性:requirepass与masterauth。其中requirepass用户指定当前主机的访问密码,而masterauth用于指定当前slave访问master时向master提交的访问密码,用于让master验证请求者身份是否合法。
1.2 repl-disable-tcp-nodelay
# Disable TCP_NODELAY on the replica socket after SYNC? # # If you select "yes" Redis will use a smaller number of TCP packets and # less bandwidth to send data to replicas. But this can add a delay for # the data to appear on the replica side, up to 40 milliseconds with # Linux kernels using a default configuration. # # If you select "no" the delay for data to appear on the replica side will # be reduced but more bandwidth will be used for replication. # # By default we optimize for low latency, but in very high traffic conditions # or when the master and replicas are many hops away, turning this to "yes" may # be a good idea. repl-disable-tcp-nodelay no
该属性用于设置是否禁用TCP特性tcp-nodelay。设置为yes则禁用tcp-nodelay,此时master与slave间的通信会产生延迟,但使用的TCP包数量较少,占用的网络带宽会较小。相反,如果设置为no,则网络延迟会变小,但使用的TCP包数量会较多,相应占用的网络带宽会变大。
知识点补充---tcp-nodelay
为了充分复用网络带宽,TCP总是希望发送尽可能大的数据块。为了达到该目的,TCP中使用了一个名为Nagle的算法。
Nagle算法的原理是,网络在接收到要发送的数据后,并不直接发送,而是等待着数据量足够大(由TCP网络特性决定)时再一次性发送出去。这样,网络上传输的有效数据的比例就等到了大大提升,无效数据的传输极大减少,于是就节省了网络带宽,缓解了网络压力。
tcp-nodelay 则是TCP协议中Nagle算法的开关。
1.3 pidfile
# If a pid file is specified, Redis writes it where specified at startup # and removes it at exit. # # When the server runs non daemonized, no pid file is created if none is # specified in the configuration. When the server is daemonized, the pid file # is used even if not specified, defaulting to "/var/run/redis.pid". # # Creating a pid file is best effort: if Redis is not able to create it # nothing bad happens, the server will start and run normally. # # Note that on modern Linux systems "/run/redis.pid" is more conforming # and should be used instead. pidfile /var/run/redis_6379.pid
如果是多实例安装(一台机器上安装多个redis实例),记得要修改这个参数。
当然,另外一些参数配置
端口号(port)、dbfilename、appendfilename、logfile、replica-priority
简单说下 replica-priority
# The replica priority is an integer number published by Redis in the INFO # output. It is used by Redis Sentinel in order to select a replica to promote【提升;晋升;】 # into a master if the master is no longer working correctly. # # A replica with a low priority number is considered better for promotion, so ##越小优先级越高 # for instance if there are three replicas with priority 10, 100, 25 Sentinel # will pick the one with priority 10, that is the lowest. # # However a special priority of 0 marks the replica as not able to perform the ##特殊的优先级的值为0 # role of master, so a replica with priority of 0 will never be selected by ##0丧失了称为master的可能性 # Redis Sentinel for promotion. # # By default the priority is 100. replica-priority 100
1.4 个性化的配置依赖参数include
################################## INCLUDES ################################### # Include one or more other config files here. This is useful if you # have a standard template that goes to all Redis servers but also need # to customize a few per-server settings. Include files can include # other files, so use this wisely. # # Note that option "include" won't be rewritten by command "CONFIG REWRITE" # from admin or Redis Sentinel. Since Redis always uses the last processed # line as value of a configuration directive, you'd better put includes # at the beginning of this file to avoid overwriting config change at runtime. # # If instead you are interested in using includes to override configuration # options, it is better to use include as the last line. # # Included paths may contain wildcards. All files matching the wildcards will # be included in alphabetical order. # Note that if an include path contains a wildcards but no files match it when # the server is started, the include statement will be ignored and no error will # be emitted. It is safe, therefore, to include wildcard files from empty # directories. # # include /path/to/local.conf # include /path/to/other.conf # include /path/to/fragments/*.conf # ################################## MODULES #####################################
例如我们想独立出一个配置文件,但是呢,只想修改几个或者少部分参数项,这时候,可以include进基本的配置文件,只把需要修改的参数,重写下即可。
二. 设置主从关系
2.1 查看
先查看下主从关系,查看指令
> info replication
在主节点上执行,
返回值 role 代表当前节点的角色;
connected_slaves的数值代表 从节点 的个数;
如果有slave节点的话,会以slave0、slave1 呈现出具体的slave信息(ip:port:state:offset:lag)。
而在从节点上执行的话,返回值是不一样的:
返回值role 代表集群角色,其他的返回值还有master_ip、master_port、master_link_status、master_last_io_seconds_age、master_sync_in_process、slave_read_only等等。
需要注意的是从节点是不可以执行写命令的,否则报错
(error)READONLY You can't write against a read only replica.
2.2 设置命令
在从节点上执行命令,如下
> slaveof host(主节点ip) port(主节点的端口号)
只执行上面的命令,如果从节点重启的话,主从关系就会失效,即丢失已设置的主从关系。
2.3. 分级管理
若redis主从集群中的slave较多时,他们的数据同步过程会对master形成较大的性能压力。此时,可以对这些slave进行分级管理。
设置方式很简单,只需要让低级别slave指定其slaveof的主机为上一级slave即可。不过,上一级slave的状态仍为slave,只不过,其是更上一级的slave。
调整主从关系,不需要关闭已有关系,再重建,而是直接执行 slaveof host port 进行调整即可。
2.4 容灾冷处理
在master/slave的redis集群中,若master出现了宕机怎么办?有两种处理方式,一种是通过手工角色调整,使slave晋升为master的冷处理;一种是使用哨兵模式,实现redis集群的高可用HA,即热处理。
无论master是否宕机,slave都可以通过下面的命令,将自己提升为master。
> slaveof no one
如果其原本就有下一级的slave,那么,其就直接变为了这些slave的真正的master了。而原来的master就会失去了这个原来的slave。
三. 主从复制原理
3.1 主从复制过程
当一个redis节点(slave)接收到类似slaveof 127.0..1 6379 的指令后直至其可以从master持续复制数据,大体经历了如下几个过程:
(1)保存master地址
当slave接收到slaveof <master_ip> <master_port>指令后,slave会立即将新的master的地址保存下来。
(2)建立连接
slave中维护着一个定时任务,该定时任务会尝试着与该master建立socker连接。
(3)slave发送ping命令
连接成功后,slave会发送ping命令,进行首次通信。如果slave没有收到master的回复,则slave就会主动断开连接,下次的定时任务会重新尝试连接。
(4)对slave身份验证
master 在接收到slave的ping命令后,并不会立即对其进行回复,而是先对Salve进行身份验证。如果验证不通过,则会发送消息拒绝连接;。验证通过,master 向slave发送连接成功响应。
(5)master持久化
slave在成功接收到master的响应后,slave向master发出数据同步请求。master在接收到数据同步请求后,fork出一个子进程,让子进程以异步方式立即进行数据持久化。
(6)数据发送
持久化完毕后,master再fork出一个子进程,让子进程以异步方式将数据发送给slave。slave会将接收到的数据不断写入到本地的持久化文件中。
在slave数据同步过程中,master的主进程仍在不断地接受着客户端的写操作,且不仅将新的数据写入到master内存,同时也写入到了同步缓存。当master的持久化文件中的数据发送完毕后,master会再将同步缓存中新的数据发送给slave,由slave将其写入到本地持久化文件中。数据同步完成。
(7)slave恢复内存数据
数据同步完毕后,slave就会读取本地持久化文件,将其恢复到本地内存数据,然后就可以对外提供服务了。
(8)持续增量复制
对外服务中master持续接收到写操作,会以增量方式发送给slave,以保证主从数据的一致性。
流程概况如下
考虑到数据发送过程中,仍由数据进来,补充如下:
3.2 数据同步演变过程
(1)sync 同步
redis 2.8 版本之前,首次通信成功后,slave会向master发送sync数据同步请求,然后master就会将其所有数据全部发送给slave,由slave保存到其本地的持久化文件中。这个过程称为全量复制。
但这里存在一个问题:在全量复制过程中可能会出现网络抖动而导致复制过程中断。当网络恢复后,slave与master重新连接成功,此时slave会重新发送sync请求,然后会从头开始全量复制。
由于全量复制过程非常耗时,所以期间出现网络抖动的概率很高。而中断后的从头开始不仅需要消耗大量的系统资源、网络带宽,而且可能会出现长时间无法完成全量复制的情况。
(2)psync
redis 2.8 版本之后,全量复制采用了psync(Partial Sync,不完全同步)同步策略。当全量复制过程出现由于网络抖动而导致复制过程中断时,当重新连接成功后,复制过程可以“断点续传”。即从断点位置开始继续复制,而不用从头再来。这样大大提升了性能。
为了实现psync,整个系统做了三个大的变化:
A. 复制偏移量
系统为每个需要传送数据进行了编号,该编号从0开始,每个字节一个编号。该编号称为复制偏移量。参与复制的主从节点都会维护该复制偏移量。
可以通过 命令info replication 的返回结果中的 slave_repl_offset (从节点)或 master_repl_offset(主节点 代表已发送出去的数据)值查看。
B.主节点复制ID
当master启动后,就会动态生成一个长度为40位的16进制字符串作为当前master的复制ID,该ID是在进行数据同步时slave识别master使用的。通过 info replication 的master_replid属性可查看到该ID。
特别注意:master redis 重启,动态生成的复制ID就会变化。
C.复制积压缓冲区
当master有连接的slave时,在master中就会创建并维护一个队列backlog,默认大小为1MB,该队列称为复制积压缓冲区。master接收到了写操作,数据不仅会写入到了master主存,写入到了master中为每个slave配置的发送缓存,而且还会写入到复制积压缓冲区。其作用就是用于保存最近操作的数据,以备“断点续传”时做数据补偿,防止数据丢失。
D. psync 同步过程
psync是一个由slave提交的命令,其格式为psync <master_replid> <repl_offset> ,表示当前slave要从指定中的repl_offset+1处开始复制。 repl_offset表示当前slave已经完成复制的数据的offset。该命令保证了“断点续传”的实现。
在第一次开始复制时,slave并不直到master的动态ID,并且一定时从头开始复制,所以其提交的psync命令为PSYNC ? -1。即master_replid 为问号(?),repl_offset为-1。
如果复制过程中断后,slave与master成功连接,则save再次提交psync命令。此时psync命令的repl_offset参数为其前面已经完成复制的数据的偏移量。
其实,并不是slave提交psync命令后就可以立即从master处开始复制,而是需要master给出响应结果后,根据响应结果来执行。master根据slave提交的请求及master自身情况会给出不同的响应结果。响应结果有三种可能:
- FULLRESYNC <master_replid> <repl_offset>:告知slave当前master的动态ID及可以开始全量复制了,这里的repl_offset一般为0。
- CONTINUE:告知slave可以按照你提交的repl_offset后面位置开始“续传”了。
- ERR:告知slave,当前master的版本低于redis 2.8 ,不支持psync,你可以开始全量复制。
psync过程概况如下
E. psync存在的问题
- 在psync数据同步过程中,若slave重启,在slave内存中保存的master的动态ID与续传需要的offset都会消失,“断点续传”将无法进行,从而只能进行全量复制,导致资源浪费。
- 在psync数据同步过程中,master宕机后slave会发生“易主”,从而导致slave需要从新master进行全量复制,形成资源浪费。
(3)psync 同步的改进
Redis 4.0 对psync进行了改进,提出了“同源增量同步”策略。
A. 解决slave重启问题
针对“slave重启时master动态ID丢失问题”,改进后的psync将master的动态ID直接写入到了slave的持久化文件中。
slave重启后直接从本地持久化文件中读取master的动态ID,然后向master提交获取复制偏移量的请求。master会根据提交请求的slave地址,查找到保存在master中的复制偏移量,然后向slave回复FULLRESYNC <master_replid> <repl_offset>,以告知slave其马上要开始发送的位置。然后master开始“断点续传”。
B. 解决slave易主问题
slave易主后需要和新master进行全量复制,本质原因是新master不认识slave提交的psync请求中的“原master的动态ID”。如果slave发送psync <原master_replid> <repl_offset> 命令,新的master能够识别出该slave要从原master复制数据,而自己的数据都是从该master复制来的。那么新master就会明白,其与该slave"师出同门",应该接收其“断点续传”同步请求。
而新master中恰好保存的有“原master的动态ID”。由于改进后的psync中每个slave都在本地保存了当前的master的动态ID,所以当slave晋升为新的master后,其本地仍保存有之前master的动态ID。而这一点也恰恰为解决“slave易主”问题提供了条件。通过master的info replication 中master_replid2 可以查看到。如果尚未发送易主,则该值为40个0。
(4) 无盘操作
Redis 6.0 对同步过程又进行了改进,提出了“无盘全量同步”与“无盘加载”策略,避免了耗时的IO操作。
- 无盘全量同步:master的主进程fork出的子进程直接将内存中的数据发送给slave,无需经过磁盘。
- 无盘加载:slave在接收到master发送来的数据后不需要将其写入到磁盘文件,而是直接写入到内存,这样slave就可快速完成数据恢复。
(5) 共享复制积压缓冲区
Redis 7.0 版本对复制积压缓冲区进行了改进,让各个slave的发送缓冲区共享复制积压缓冲区。这使得复制积压缓冲区的作用,除了可以保障数据的安全性外,还作为所有slave的发送缓冲区,充分利用了复制积压缓冲区。
学习参阅特别声明
【Redis视频从入门到高级】
【https://www.bilibili.com/video/BV1U24y1y7jF?p=11&vd_source=0e347fbc6c2b049143afaa5a15abfc1c】