目录
3.4、补充:redis服务器启动和停止的命令,需要搭配使用
1、单点问题
什么是单点问题:
单点问题指的是 某个服务器,只存在一个物理服务器来部署这个服务器程序,也就是只有一个节点,那就会有两个比较大的问题:
- 可用性问题:当这个服务器挂了(如断电了,硬盘坏了等等)时,就意味着服务就会中断,用户需要等待服务器重启后才能继续使用~
- 性能问题:只有一个节点,该服务器所支持的并发量就会比较有限
解决单点问题:
引入分布式系统中,其实主要是解决了单点问题~
同理对于Redis,在分布式系统中,就是希望有多个服务器来部署Redis服务,从而构成一个Redis集群,此时就可以让这个集群给整个分布式系统提供更稳定更高效的数据存储功能~
在分布式系统中,为了使用多个服务器来部署Redis,有以下几种部署方式:
- 主从复制
- 主从+哨兵模式
- 集群模式
2、理解主从复制
在若干个Redis节点中,在其中指定某个节点是主节点,指定其他为从节点。
主从节点的规则:
- 从节点需要听从主节点。--->主节点保存数据,从节点的数据直接从主节点复制过来
- 从节点上的数据需要和主节点保持一致。--->有了从节点后,修改数据只能在主节点上修改(从节点的数据只能读,不能写),修改后主节点把数据同步给从节点
主从复制解决的问题:
使用主从复制,虽然可以有效的解决单点问题到的性能问题,但是如果当主节点挂了时,对于数据的修改还是不能进行的,所以可用性还没有处理的很完善~
准确来说,主从复制,提高的其实是对于读操作的可用性和性能~
3、配置Redis主从结构
由于我只有一个云服务器,所以我以下的说明,都是以在一个云服务上开启多个Redis服务器的方式来实现主从结构~
3.1、在一个云服务器上如何启动多个Redis服务器:
我们在启动多个Redis服务器时,需要保证多个redis-server的端口是不同的,默认情况下是6379,那么在我们新启动的redis-server就不能再使用6379了。指定redis-server的端口的两种方式:
- 在启动程序时,通过命令来指定端口号:--port
- 在配置文件中设定端口
以下举例为,在配置文件中设定端口~
如何配置:
主节点,不需要配置,配置从节点即可:
复制的命令:
上述一共算是我创建了三个从节点,现在我们把三个从节点的配置文件修改一下即可:
启动前:
启动:
启动后,现在只是启动了多个Redis服务器,但是这四个Redis服务器之间,没有任何关联,并不是主从结构
验证几个服务器没有关联:
大家可以打开两个Redis服务器,往一个Redis中存储一些数据,查看另一边是否存在刚才存入的数据~我就不演示了
3.2、配置主从复制
配置成主从结构,有三种方式:
- 在配置文件中加入slaveof {masterHost} {masterPort}随Redis启动生效
- 在redid-server启动命令时加入 --slaveof {masterHost} {masterPort}生效
- 直接使用redis命令:slaveof {masterHost} {masterPort}生效
说明:第一种配置文件,在配置文件末尾加上,如下:
第二种方式已经很清楚了,就不说明了
第三种方式,就是你已经进入客户端了,再执行命令:
就是在这里就行上述的命令
以上三种方式,建议使用第一种,修改后,重新启动服务器,是持久生效的【修改配置文件,一定要重启后才能生效~】
3.3、查看是否配置成功
方法一:
我们来查看网络信息:使用命令:netstat -anp | grep redis-server
可以看到redis服务器的这四个进程所对应的端口号,并且,往下看,还能看到其他的一些tcp连接,他其实体现的就是主从节点之间的情况,是成对对出现的:
每一对,就是redis主节点和从节点之间的tcp连接,当从节点启动后和主节点建立tcp连接,主节点相当于服务器,从节点就相当于客户端
方法二:
做数据去看,看能不能在从节点上添加数据,主节点的数据能不能同步到从节点中:
3.4、补充:redis服务器启动和停止的命令,需要搭配使用
命令搭配1:
- 启动:redis-server 配置文件名
- 停止:kill -9 进程id
命令搭配2:
- 启动:service redis-server start
- 停止:service redis-server stop
通常都是使用命令搭配1
因为如果使用命令搭配的启动,使用kill的方式停止,这个redis-server进程能自动启动~
3.5、查看主从结构信息
我们进入redis客户端,先看主节点上,输入命令:info replication 返回如图:
从节点上:
3.6、断开 / 修改主从结构
断开主从结构的命令:slaveof no one --->这个命令直接在redis客户端中执行:
修改主从结构:
在上述断开后,我们可以使用命令:slaveof {masterHost} {masterPort}来设置新的主从结构【从节点也可以有从节点】
此时,6381既是6379的从节点,也是6380的主节点,同步数据时,最大的主节点才能够被修改数据,先同步到自己的子节点,再由其子节点同步到他们的子节点上~
此时的主从结构的修改只是暂时的,当重启redis服务器后,仍然会按照配置文件中的设置来建立主从关系~
4、主从复制时的安全性、只读、传输延迟
安全性
对于数据比较重要的节点,主节点会通过设置requirepass参数进行密码验证,这时所有的客户端访问必须要使用anth命令进行校验。从节点与主节点的复制连接是通过一个特殊标识的客户端来完成,因此需要配置从节点的mastererauth参数与主节点密码保持一致,这样从节点才可以正确的连接到主节点 并 开始复制流程~
只读
默认情况下,从节点使用slave-read-only=yes配置为只读模式。由于复制只能从主节点到从节点,对于从节点的任何修改主节点都是无法感知到的,修改从节点会造成主从数据不一致。所以建议线上不要修改从节点的只读模式
传输延迟
主从节点在正常情况下都是部署在不同的机器上,复制是的网络延迟,是不可避免的~
Redis中为我们提供了repl-disable-tcp-nodelay参数用于控制是否关闭TCP_NODELAY,默认为no,即开启了tcp-nodelay功能。其实就是内部支持了nagle算法(默认开启),需不需要开启,需要根据具体的业务场景,其优缺点如下:
- 开启:增加tcp的传输延迟;节省了网络带宽
- 关闭:减少tcp的传输延迟;增加了网络带宽
5、拓扑结构——各个节点之间的组织方式
Redis的复制拓扑结构可以支持多层或多层复制关系,根据拓扑复杂性,可以分为以下三种:一主一从、一主多从、树状主从结构。
一主一从结构:
如果写数据请求过多,主节点还有会有一些压力的
可以通过关闭主节点的AOF,从节点上开启AOF。【此方式也会有缺陷:主节点如果挂了,不能让他自动重启,因为此时他没有AOF文件,启动后,会将从节点的数据页干掉了。优化一下就是当主节点挂了后,需要让主节点从 从节点这里获取到AOF文件后再重启~】
一主多从结构:
主节点上的数据被修改时,就会把改变的数据同时同步给所有的从节点,随着从节点个数的增加,同步一条数据,就需要传输很多次~
树状结构:
- 优点:使用这种结构,主节点需要的网络带宽就不会那高了
- 缺点:同步的延迟更长了~
6、主从复制的流程
流程图:
说明:
- 不论是配置文件还是命令输入,只要执行了slaveof 127.0.0.1 6379这个操作,就会主从复制~
- 保存主节点信息:保存主节点的ip和端口号
- 主从建立连接:就是TCP的连接【是系统层面的,其中的三次握手,就是在验证验证通信双方能否正确读写数据(车路)】。注:如果从节点无法建立连接,定时任务会无限重试直到连接成功或用户停止主从复制为止
- 发送ping命令:验证主节点是否能够正常工作【是应用程序层面的(车跑)】。注:如果ping命令的结果pong返回超时,从节点会断开tcp连接,等待定时任务下次重新建立连接
- 权限验证:Redis主节点开启了密码时,会有此步骤。如果密码验证失败,从节点的复制就会停止
- 同步数据集:这里就是全量同步->将主节点的所有数据都同步到从节点中。此时会比较耗时
- 命令持续复制:这里是增量同步->持续将主节点中有修改的数据同步过来~
7、命令psync完成数据同步的过程
Redis使用psync命令完成主从数据同步,同步过程分为全量复制和增量复制。
在Redis中psync命令并不需要我们手动执行,Redis服务器会在建立好主从同步关系后,自动执行psync。从节点负责执行psync,从节点从主节点那边拉取数据~
psync命令,也可以手动执行,语法格式:psync replicationid offset --->两个参数的含义如下:
7.1、replicationid
replication:复制的意思
replicationid由谁生成?何时产生?
replicationid由主节点生成的~
replicationid在主节点启动的时候就会生成;当从节点晋升为主节点时,也会生成;同一个主节点,重启时,replicationid也是不同的~
replicationid存在的意义?
Redis的主从节点建立了复制关系,从节点就会从主节点这里获取到replicationid~也就是说,从节点要知道谁是他的主节点~【不仅存在一主多从,也存在多主多从】
查看replicationid
使用我们上面提到过的查看主从结构信息的命令:info replication
上述replid则是其缩写
上述信息中,为什么存在master_replid2?
场景:A为主节点,B为从节点
此时,B中会记录着A的replid,当出现网络抖动时,B会以为是A挂了,B就会自己晋升为主节点,于是B就会给自己分配新的replid,再使用replid2来记录A原本的replid,当网络恢复后,B就根据replid2找回之前的主节点,如果网络没有恢复,B此时就是主节点可以继续处理后续数据
7.2、offset
offset:偏移量的意思
offset偏移量具体指的什么?
以主节点为例:主节点上会收到很多修改操作的命令,每个命令占几个字节,每个命令字节的累加就是主节点的偏移量~
同理,从节点的偏移量就是从节点上数据同步的位置在哪儿
因此,offset偏移量是每个节点都会维护自己的偏移量~
7.3、再次来看psync
根据上述对replicationid和offset的解释,我们总结来说就是,replicationid和offset共同描述的是一个“数据集合”,两个节点的replicationid和offset一致时,说明其存储的数据就是完全一致的~
因此,psync这里可以从主节点获取全量数据,也可以是一部分数据。主要是要看offset的进度,当offset为-1时,则是全量数据,offset为其他正整数时,需要再次考虑是否是复制部分数据~
psync的运行流程图:
说明:
- 从节点向主节点发送psync操作时,replid和offset的默认值为 ? 和 -1【默认为全量复制】主节点有三种返回情况
- 情况1:全量数据同步。
- 情况2:增量数据同步
- 情况3:老版本的redis服务器不支持psync,使用sync替换一下
具体什么时候要进行全量复制,什么时候进行部分复制,继续看下文~
8、全量复制
8.1、什么时候进行全量复制
- 主从节点首次进行数据同步
- 主节点不方便进行部分复制
8.2、全量复制的流程图
图:
说明:
- 1)从节点发送psync命令给主节点进行数据同步,由于是第一次进行复制,从节点没有主节点的replid和offset,所以发送的是psync ? -1
- 2)主节点根据命令,解析出要进行全量复制,回复+FULLRESYNC响应
- 3)从节点接收主节点的运行信息进行保存
- 4)主节点执行bgsave进行RDB文件的持久化【为什么要现在进行rdb文件持久化:1:rdb是二进制文件,比较省空间;2:不使用已有的rdb文件,要保证数据是最新的】
- 5)主节点发送RDB文件给从节点,从节点保存RDB文件到本地硬盘
- 6)主节点将从生成RDB到接收完成期间执行的写命令,写入到缓冲区中,等从节点保存完RDB文件后,主节点再讲缓冲区中的数据补发给从节点 ,补发的数据仍然按照rdb文件的二进制格式追加到从节点收到的rdb文件中,保持主从一致
- 7)从节点清空自身原有的旧数据
- 8)从节点加载RDB文件得到与主节点一致的数据
- 如果从节点加载RDB完成后,并且开启了AOF持久化功能,他会进行bgrewrite操作,得到最近的AOF文件【因为前面的数据可能存在大量冗余,所以使用AOF来整理一下也是有必要的】
8.3、无硬盘模式(diskless)的全量复制
无硬盘模式,就是上述流程中的关于文件操作的地方,都给去掉~
- 主节点生成的rdb的二进制数据,不保存到文件中,直接进行网络传输
- 从节点收的rdb数据,不进行保存,直接将数据进行加载
虽然引入了无硬盘模式,但是全量复制仍然是比较重量的,比较耗时的~因为网络传输是省不了的~
9、部分复制
9.1、什么时候进行部分复制
- 从节点之前已经从主节点上复制过数据了,但因为网络抖动或者从节点重启了
- 从节点需要重新从主节点同步数据,当大部分数据一致时,需要进行部分复制
9.2、部分复制的流程图
图:
说明:
- 1)当主从节点之间出现网络中断时,如果超过repl-timeout时间,主节点会认为从节点故障并中断复制连接
- 2)主从连接中断期间主节点依然相应命令,但这些写命令都因为网络中断无法及时发送给从节点,所以暂时将这些命令滞留在复制积压缓冲区中
- 3)当从节点网络恢复后,从节点再次连上主节点
- 4)从节点将之前保存的replicationid和offset作为psync的参数发送给主节点,请求部分复制
- 5)主节点接到pysnc,进行必要的验证。随后根据offset去复制积压缓冲区查找合适的数据,并响应给+COUNTINUE给从节点
- 6)主节点将需要从节点同步的数据发送给从节点,最终完成一致性
9.3、积压缓冲区
repl-backlog-buffer-->积压缓冲区
内部就是一个环回队列,只会记录最近一段时间修改数据,总量有限,随着修改操作的增多,旧的数据逐渐删掉~
9.4、主节点如何验证是全量复制还是部分复制
第一步:查看replicationid,如果这个id不一样,则说明他们之间未进行过数据同步,所以使用全量复制
第二步:结合offset和积压缓冲区来判断。当从节点的offset在积压缓冲区中,则进行部分复制,否则进行全量复制
10、实时复制
10.1、什么时候进行实时复制
当从节点已经和主节点同步好了数据,但是之后主节点收到后续操作,要再次进行修改数据时,此时就要同步给从节点,也就是实时同步~
10.2、具体实现
主从节点之间建立tcp连接,然后主节点把自己收到的修改数据的请求通过上述的连接发送给从节点,从节点再根据这些请求修改自己的数据即可~
这个过需要一定的时间,正常来说时间是比较短的,但是主从结构的使用树状结构时,层级越多,延时就会上升~
10.3、心跳包
在进行实时复制时,需要保证连接要处于可用状态~谁来负责检查是否可用呢——心跳包
心跳包机制的实现:
- 主从节点彼此都有心跳检测机制,各自模拟成对方的客户端进行通信
- 主节点:默认,每个10s给从节点发送一个ping命令,从节点收到后返回pong
- 从节点:默认,每隔1s就给主节点发送一个特定的请求,机会上报当前从节点的复制数据的进度(offset)
- 默认等待响应时间:60s,超过时间,就会判定对方出事了,就会断开复制客户端连接。从节点恢复连接后,心跳机制继续进行
11、主从复制的缺点
- 从机多了, 复制数据的延时⾮常明显.
- 主机挂了, 从机不会升级成主机. 只能通过⼈⼯⼲预的⽅式恢复【想要让从节点自动晋级,需要哨兵来辅助】
12、 区分runid、replicationid
- runid每个节点都是不同的,只是标识了redis的运行,每次运行runid就会自增【在哨兵中起作用】
- replicationid具有主从关系节点的id都是相同的【主要在主从复制中起作用】
好啦,就到这里啦,下期见啦~