1.主从复制是怎么回事?
分布式系统, 涉及到一个非常关键的问题: 单点问题
单点问题:如果某个服务器程序, 只有一个节点(只搞一个物理服务器, 来部署这个服务器程序)
1.可用性问题,如果这个机器挂了,意味着服务就中断了~
2.性能/支持的并发量也是比较有限的~
引入分布式系统,主要也就是为了解决上述的单点问题子
在分布式系统中,往往希望有多个服务器来部署 redis 服务,从而构成一个 redis 集群~~,此时就可以让这个集群给整个分布式系统中其他的服务,提供更稳定/更高效的数据存储功能~~
在分布式系统中,希望使用多个服务器来部署 redis,存在以下几种 redis 的部署方式~~
1.主从模式
2.主从+哨兵模式
3.集群模式
1.1 主从模式
- 在若干个 redis 节点中, 有的是"主"节点,有的是"从"节点
- 假设有三个物理服务器(称为是三个节点)
- 分别部署了一个 redis-server 进程~~
- 此时就可以把其中的一个节点,作为"主节点”
- 另外两个节点作为"从节点”
- 从节点,得听主节点的~~
- (从节点上的数据要跟随主节点变化; 从节点的数据要和主节点保持一致)
- 本来,在主节点上保存一堆数据,引入从节点之后,就是要把主节点上面的数据,复制出来,放到从节点中
- 后续,主节点这边对于数据有任何修改,都会把这样的修改给同步到从节点上(从节点,就是主节点的副本)
- 如果我改了从节点的数据,是否是把从节点的数据往主节点上同步呢??
- Redis 主从模式中, 从节点上的数据,不允许修改!!! 只能读取数据!!
2 主从复制解决的问题
- 更准确的说,主从模式,主要是针对“读操作”
进行 并发量 & 可用性 的提高~~
而写操作的话,无论是可用性还是并发,都是非常依赖主节点.主节点又不能搞多个~~
实际业务场景中,读操作往往就是比写操作更频繁~~
3.如何启动多个redis-server
- 配置 redis 主从结构,首先需要启动多个 redis 服务器~~
- 正常来说, 每个 redis 服务器程序,应该在一个单独的主机上(才是 分布式 )
- 但是当前,同学们每个人手里,只有一个云服务器~~(可以在一个云服务器主机上,运行多个 redis-server 进程的~~)【此处需要保证多个 redis-server 的端囗是要不同的】
- 本来 redis-server默认的端口是 6379
此时就不能让新启动的 redis-server再继续使用 6379 了. - 如何去指定 redis-server 的端口呢?
- 1.可以在启动程序的时候, 通过命令行来指定端口号. --port 选项
- 2.也可以直接在配置文件中, 来设定端口~~(此处准备搞一个主节点,两个从节点.主节点的配置不用变~~只需要修改从节点的配置即可~~)
- 复制原有的文件到新的文件夹
- 修改从配置文件
- 1.改端口号
- 2.daemonize:yes(按照后台的方式进行运行)
4 配置主从复制
【question】
这两个进程相互独立
要想配置成 主从结构,就需要使用 slaveof
1.在配置文件中加入 slaveof {masterHost}{masterPort} 随 Reds 启动生效,(修改了配置文件,一直持久生效的)
2.在 redis-server 启动命令时加入-slaveof(masterHost}{masterPort)生效
3.直接使用 redls 命令:slaveof {masterHost}{masterport} 生效
- 此处以 6379 为主节点.6380 和 6381 为从节点·
- redis 服务器的配置文件改完了之后,就需要重新启动才能生效!!
- 这种停止 redis-server 的方式,是和 咱们之前通过 直接运行 redis-server 命令的方式搭配的~~
- 而如果是使用 service redis-server start 这种方式启动的(此时如果使用 kil -9 的方式停止,kil 掉之后,这个 redis-server 进程能自动启动~~),就必须使用 service redis-server stop 来进行停止~~
- 上述原因:(往往会有另外一个进程来专门监控指定的服务器进程的运行状态~)
- 服务器就是要稳定性和高可用~
- 但是服务器上的某些程序,可能也难以避免出现挂了的情况
如果服务器进程挂了,要是能自动重启进程(把进程再启动起来),对于整体的服务不会产生严重影响~~- 重新运行(启动两个从节点)
- 多了一些tcp连接
5.查看主从结构信息
- 从节点还可以再挂从节点
6.断开主从结构和修改主从结构
- slaveof no one(直接在 redis 客户端中的命令)
- 直接使用 这个命令 断开现有的主从复制关系~~
- 从节点断开主从关系,它就不再从属于其他节点了,里面已经有的数据,是不会抛弃的!!
- 但是,后续主节点如果针对数据做出修改,从节点就无法再自动同步数据了.
- 此时 6380 看起来向是个主节点
实际上不是,仍然是从节点
只是作为 6381 同步数据的来源,自身仍然是不能修改数据的~- - 刚才通过 slaveof 是修改了主从结构~~
- 此处的修改是临时性的.如果重新启动了 redis 服务器,仍然会按照最初在配置文件中设置的内容来建立主从关系~~
7.主从复制的安全,只读,传输延迟
7.1 安全性
7.2 只读
- "主从复制"是从主,到从~~
- 不能从 从节点 到 主节点 ~~
- 如果从节点允许修改,后续对于从节点的修改,主节点是感知不到的.数据就不一致了~~
7.3 传输延迟
- 主节点和从节点之间通过网络来传输(TCP)
- TCP 内部支持了 nagle 算法~~(默认开启的)
- 开启了,就会增加 tcp 的传输延迟节省了网络带宽
- 关闭了,就会减少 tcp 的传输延迟~ 增加了网络带宽
- 【目的和 tcp 的捎带应答是一样的针对小的 tcp 数据报,进行合并. 减少了包的个数~~】
- repl-disable-tcp-nodelay这个选项可以用于在主从同步通信过程中,关闭 tcp 的 naqle 算法~~从节点更快速的和主节点进行同步~~
8.拓扑结构
若干个节点之间,按照啥样的方式来进行组织连接~~
- 如果写数据请求太多~~此时也是会给主节点造成一些压力~~可以通过关闭主节点的 AOF, 只在从节点上开启 AOF.
- 但是,这种设定方式,有一个严重的缺陷~~ 主节点一旦挂了,不能让他自动重启..(如果自动重启此时没有 AOF 文件,就会丢失数据,进一步的主从同步,会把,从节点的数据也给删了)
- 改进办法,当主节点挂了之后, 就需要让主节点从从节点这里获取到 AOF 的文件.再启动~~
- 实际开发中, 读请求, 远远超过 写请求
- 主节点上的数据发生改变, 就会把改变的 数据同时 同步给所有的从节点~随着从节点个数的增加,同步一条数据,就需要传输多次~~
- 改进
- 主节点就不需要那么高的网卡带宽了~~
一旦数据进行修改了,同步的延时是比刚才更长的~~
9.主从复制的基本流程
10.replicationid的作用
- redis 提供了 psync 命令,完成数据同步的过程。
- psync 不需要咱们手动执行
- redis 服务器会在建立好主从同步关系之后,自动执行 psync
- 从节点负责执行 psync.从节点从主节点这边拉取数据~~
- replication 复制~
- 是主节点生成的。主节点启动的时候就会生成~~
- 从节点晋升成主节点的时候,也会生成~(即使是同一个主节点,每次重启,生成的 replication id 都是不同的)
- 从节点和主节点建立了复制关系,就会从主节点这边获取到 replication id
- 【当前,此处讨论的都是 一个主节点 多个从节点
后面谈到 集群 的时候,多个主节点,多个从节点了】- info replication 获取到当前 replication id 的值~~
- 一般情况下 replid2 这个是用不上的~~
- 有一个主节点 A(生成 replid),还有一个从节点 B(获取到 A 的replid)
- 如果 A 和 B 通信过程中出现了一些网络抖动~~
- B 可能就会认为 A 挂了~~
- B 就会自己成为主节点~~(给自己生成一个 replid)
- 此时,B 也会记得, 之前 旧的 replid,就是通过 replid2
- 后续网络稳定了,B 还可以根据 replid2 重新回到 A 的怀抱~~
- 需要手动干预~~
哨兵机制, 可以自动完成这个过程
11.offset的作用
- 主节点和从节点上都会维护 偏移量 (整数)
- 主节点的偏移量,主节点上会收到很多的修改操作的命令~~
- 每个命令都要占据几个字节~~
- 主节点会把这些修改命令,每个命令的字节数进行累加~
- 从节点的偏移量,就描述了,现在从节点这里数据同步到哪里了~~
- 从节点(slave)每秒钟上报自身的复制偏移量给主节点
- replication id(数据来源) 和 offset(获取进度) 共同描述了一个"数据集合
- 如果发现两个机器,replication id 一样,offset 也一样,就可以认为这两个 redis 机器上存储的数据就是完全一样的!!
12.全量复制和部分复制
- psync 这里可以从主节点获取全量数据,也可以获取一部分数据
- 主要就是看 offset 这里的进度~~
- offset 写作 -1,就是获取全量数据
- offset 写具体的正整数,则是从当前偏移量位置来进行获取~~
- 获取所有数据,是最稳妥的,但是会比较低效
- 如果从节点之前已经从主节点这里复制过一部分数据了就只需要把新的之前没复制过的数据搞过来即可~~
- 不是从节点索要那部分,主节点就一定给哪部分~~
- 主节点会自行判定,看当前是否方便给部分数据~~不方便就只能给全量了~~
- 啥时候进行全量复制:
1.首次和主节点进行数据同步
2.主节点不方便进行部分复制的时候 - 啥时候进行部分复制:
从节点之前已经从主节点上复制过数据了.因为网络抖动或者从节点重启了从节点需要重新从主节点这边同步数据,此时看看能不能只同步一小部分(大部分数据都是一致的)
12.1 全量复制的流程
从节点主动进行触发
12.2 全量复制的无硬盘模式
- 主节点,进行全量复制的时候,也支持"无硬盘模式"(diskless)
- 主节点,生成的 rdb 的二进制数据,不是直接保存到文件中了~~而是直接进行网络传输了~~(省下了一系列读硬盘和写硬盘的操作)
- 从节点,之前,也是先把收到的 rdb 数据,写入到硬盘中,然后再加载~~ 现在也可以省略这个过程,直接把收到的数据进行加载了~~
- 即使引入了无硬盘模式,仍然整个操作是比较重量,比较耗时的网络传输(大规模数据(全量复制))是没法省的~~相比于网络传输来说,读写硬盘是小头~
12.3 关于runid和replid
- 1个 redis 服务器上, replication id 和 run id 是都存在的!!!
- 两个不同的 id,看起来非常像~~
12.4 全量复制的流程
- 从节点要从主节点这里进行全量复制.全量复制,开销是很大的.
- 有些时候,从节点本身已经持有了主节点的绝大部分数据,这个时候,就不太需要进行全量复制了
- 比如,出现网络抖动~~ 主节点这边最近修改的数据可能就无法及时同步过来了~~更严重的,从节点已经感知不到主节点了~~(进一步的从节点可能会升级成主节点)
- 网络抖动,一般都是"暂时的",过一会就恢复了~~此时就可以让从节点和主节点重新建立联系~~
- 当从节点和主节点重新建立连接之后,就需要进行数据的同步~~
- psync 带有具体的 replid 和 offset 值.主节点就要根据 psync 的参数进行判定~~当前这次是按照全量复制合适还是部分复制合适~~
12.5 实时复制的流程
- 全量复制: 从节点刚连上主节点之后,进行的数据初始化工作.
- 部分复制: 全量复制的特殊情况,优化手段,目的和全量复制一样
- 实时复制: 从节点,已经和主节点,同步好了数据了~~(从节点这一时刻已经和主节点数据一致了但是之后,主节点这边会源源不断的收到新的修改数据的请求.
- 主节点上的数据就会随之改变,也需要能够同步给从节点
- 从节点和主节点之间会建立 TCP 的长连接~~
- 然后主节点把自己收到的修改数据的请求,通过上述 连接,发给从节点从节点再根据这些修改请求,修改内存中的数据~【这个过程也是需要时间的~正常来说,这个延时是比较短的.但是如果是多级从节点的 树形结构 ~~如果这里从节点的级别很多~~(有很多层),,延时也就会上升】
- 在进行实时复制的时候,需要保证连接处于可用状态~~
- 心跳包 机制~
- 主节点: 默认, 每隔 10s 给从节点发送一个 ping 命令.从节点收到就返回 pong
- 从节点: 默认, 每隔 1s 就给主节点发起一个特定的请求,就会上报当前从节点复制数据的进度(offset)
13.主从复制小结
主从复制解决的问题:单点问题.1. 单个 redis 节点, 可⽤性不⾼.2. 单个 redis 节点, 性能有限.主从复制的特点:1. Redis 通过复制功能实现主节点的多个副本。2. 主节点⽤来写, 从节点⽤来读. 这样做可以降低主节点的访问压⼒.3. 复制⽀持多种拓扑结构,可以在适当的场景选择合适的拓扑结构。4. 复制分为全量复制, 部分复制和实时复制。5. 主从节点之间通过⼼跳机制保证主从节点通信正常和数据⼀致性。主从复制配置的过程:1. 主节点配置不需要改动.2. 从节点在配置⽂件中加⼊ slaveof 主节点 ip 主节点端⼝ 的形式即可.主从复制的缺点:1. 从机多了, 复制数据的延时⾮常明显.2. 主机挂了, 从机不会升级成主机. 只能通过⼈⼯⼲预的⽅式恢复.
14.问题
14.1 从节点何时晋升成主节点
- 主从复制,最大的问题还是在主节点上主节点挂了,从节点就迷茫了~~
- 虽然能够提供读操作,但是从节点不能自动的升级成主节点~~
- 不能替换原有主节点对应的角色~~
- 此时,就需要程序猿/运维手工的恢复主节点~~(非常繁琐的)
- Redis 哨兵~~ 自动的对挂了的主节点进行替换~~
- 从节点和主节点之间断开连接,有两种情况:
- 1.从节点主动和主节点断开连接.
- slaveof no one
- 这个时候,从节点,就能够晋升成主节点~~
- 意味着我们程序猿要主动修改 redis 的组成结构~~
- 2.主节点挂了~~
- 这个时候,从节点,不会晋升成主节点的~
- 必须通过人工干预的方式,恢复主节点~~
- 这个是脱离咱们掌控的~~ 高可用下的一个典型问题~-
14.2 关于redis主节点无法重启的问题
- 解决方案:
- 把三个 redis 服务器的生成的文件,也给区分开~~更靠谱的是,直接把三个 redis 服务器的 工作目录 区分开~~(修改 配置文件 中的 dir 选项)
- 1.停止之前的 redis 服务器~~
- 2.删除之前工作目录下 已经生成的 aof 文件~~或者也可以通过 chown 命令修改 aof 文件所属的用户~~
- 3.给从节点创建出新的目录~用来作为从节点的工作目录~并且修改从节点的配置文件,设定成新的目录为工作目录
- 4.启动 redis 服务器~~