Redis主从复制
- 什么是主从复制(来自小姐姐的面试题72)?
- 使用一个redis实例作为主机,其余的作为备份机。主机和备份的数据完全一致,主机支持写入和读取操作,而从机只支持数据同步和读取操作。客户端将数据写入当主机,由主机自动将数据同步到从机。因而可以将写入数据的命令发送给主机执行,读取数据的命令发送给不同的从机执行,达到读写分离的目的。(64为mysql的主从同步原理)
- slave从节点不会竞选成为master,因为每个客户端连接redis实例时都指定了ip和端口号,如果所连接的redis实例故障下线了,而主从模式没有提供手段通知客户端另外可连接的客户端地址,则需要手动更改客户端配置重新连接。
- 优点:7点
- 一个master可以同步多个slaves
- slave同样可以接收其他slaves的连接和同步请求,有效分载master的同步压力
- master server是以非阻塞的方式为slaves提供服务,在master-slave同步期间,客户端仍然可以提交查询或修改的请求
- slave server也是以非阻塞的方式完成数据同步,在同步期间,客户端提交查询请求,则返回同步前的数据
- 为了分载master的读操作压力,slave服务器可以为客户端提供只读操作的服务,写服务由master来完成,系统的伸缩性得到了很大的提高
- master可以将数据保存操作交给slaves完成,避免在master中要有独立的进程来完成此操作(不是写操作由master完成吗?)
- 应该是由Master写到内存,然后slaves同步到自己的里面的
- 支持主从复制,主机会自动将数据同步到从机,读写分离
- 缺点:4点
- redis不具备自动容错和恢复功能,主从机宕机都会导致前端部分读写请求失败,需要等待重启或手动切换前端ip才能恢复
- 主机宕机前有部分数据未能及时同步到从机,切换ip后数据不一致,降低系统可用性
- redis的主从复制采用全量复制,复制过程中主机会fork出一个子进程对内存做一份快照,并将子进程对内存快照保存为文件发送给从机。需要确保主机有足够多的内存空间,若快照文件较大,对集群对服务能力会产生较大的影响。而且复制过程是在从机新加入或从机和主机网络断连时都会进行,也就是网络波动会造成主机和从机间的一次全量复制,对系统运营造成麻烦。
- redis较难支持在线扩容,运维人员在系统上线时必须确保有足够的空间,这对资源造成很大浪费
- 主从复制的作用主要包括:
- 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
- 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复,实际上是一种服务的冗余
- 负载均衡:在主从复制的基础上,,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(就是写redis数据时应用连接主节点,读redis数据时,应用连接从节点),分担服务器负载,尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高redis服务器的并发量
- 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础
- 一般来说Redis在项目中,不可能是一台的,当然也有,我之前做的就是
- 从结构上,单个Redis服务器存在单点故障问题,并且一台服务器需要处理所有的请求负载,压力较大
- 从容量上,单个Redis服务器内存容量有限,就算一台Redis服务器内存容量为256G,也不可能将所有内存用作Redis的存储内存,一般来说线上服务器,单台Redis最大使用内存不应该超过20G
- 电商网站上的商品,一般都是一次上传,无数次浏览,其实就是读多写少
- 对于这种场景我们可以使用下面这种架构
环境搭建
启动源redis
连接查看信息
[root@localhost bin]# redis-cli 连接客户端 127.0.0.1:6379> info replication NOAUTH Authentication required. 127.0.0.1:6379> auth 123456 #认证 OK 127.0.0.1:6379> info replication 查看redis的信息 # Replication role:master #当前位主节点 connected_slaves:0 #没有从节点 master_replid:32128903c20911483fef0c990175fc21c4139fac master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 127.0.0.1:6379> config set requirepass "" # 设置密码为空,老麻烦了,老需要认证 OK 127.0.0.1:6379>
打开四个窗口,从左到右称为A B C D,上面的操作是A完成的
全部切换到 /usr/local/bin 目录下
A,关闭redis,因为刚才连接查看信息,后还在连接中,执行shutdown就可以了
A,查看服务已经关闭
A进入到redisConfig目录下,拷贝三份配置文件,拷贝redis.conf为 redis-6379.conf redis-6380.conf redis-6381.conf,因为默认的端口是6379,我是端口号直接往上加的,不用原来的配置文件,防止修改错误
A,修改redis-6379.conf redis-6380.conf redis-6381.conf三个配置文件
vi redis-6379.conf logfile "" 修改为 logfile "6379.log" dbfilename dump.rdb 修改为 dbfilename dump-6379.rdb vi redis-6380.conf port 6379 修改为 port 6380 pidfile /var/run/redis_6379.pid 修改为 pidfile /var/run/redis_6380.pid logfile "" 修改为 logfile "6380.log" dbfilename dump.rdb 修改为 dbfilename dump-6380.rdb vi redis-6381.conf port 6379 修改为 port 638 pidfile /var/run/redis_6379.pid 修改为 pidfile /var/run/redis_6381.pid logfile "" 修改为 logfile "6381.log" dbfilename dump.rdb 修改为 dbfilename dump-6381.rdb
A运行redis-6379.conf
B运行redis-6380.conf
C 运行redis-6381.conf
D 执行查看服务
一主二从配置(命令配置,命令配置是暂时的,就像设置密码一样缓存丢失,密码失效):
默认情况下,每台服务器都是主节点
只需要配置从机就可以了
规划:6379为主,80 81为从
A B C 都连接自己的redis进入cli界面
A:
B:
C:
只需要配置从节点就可以了,主节点不用动
B:执行设置主节点
命令:slaveof ip port
A:查看自己节点信息
C:执行设置主节点
A:查看自己的节点状态
一主二从搭建完成
配置文件配置(上面配置文件中没有写,在这里写)
# replicaof <masterip> <masterport> 删除前面的井号, 然后 后面的两个标签 分别是写 ip 和 端口的
# masterauth <master-password> 如果主节点有密码,删除前面的井号,后面的标签 写主节点的密码就可以了
刚才的命令也是在配置replicaof获取一下就看见了
B 获取从机配置文件中的replicaof
可以看到 就是IP 和端口
测试:
主机断开后,丛机依旧能获取到数据,但是这个时候没有了写操作,并且丛机不能自动提升为主机
主机重启成功后,从节点会自动连接到主节点,这个时候丛机依旧可以从主节点同步
如果丛机是采用命令行配置的主从,那么丛机宕机后重启就会自动变回原来的主节点,需要重新设置为从节点,并且在第一次连接主节点的时候,做全量数据复制,之后做增量复制
这种是默认的一主二从
架构的演变(层层链路模式)
6379为主节点,他的子节点是6380,6380的子节点是6381,所以他是从节点也是主节点,当然在6379还活着的时候他是从节点,如果6379宕机了,那么6380可以通过 slaveof no one使自己变成主节点,当然是手动的,但是层层链路有个问题,那就是中间节点宕机了,那么需要手动将他的下级节点指向他的上级节点,也就是说将6381指向6379,来完善链路
这里就可以有我想到了一个解决方案:
因为这个层层链路本省就是一个链表我们可以在,内存中维护这个链表,一旦中间的节点宕机,我们将这个链拿出来,等待重启之后添加到最后面,并指定他的主节点为最后一个层节点
类似于 1->2->3->4->5
在这个时候3宕机了,那么4直接指定自己的父节点为2
等3重启之后,直接指定自己的父节点为5就变成了
1->2->4->5->3
当然在工作中这些都是不用的[那我在学什么[手动滑稽]]
redis主从复制的核心原理(来自小姐姐的面试题73)
通过执行slaveof命令设置slaveof选项,当写操作导致数据变化时会自动将数据同步给从数据库,一个主库可以有多个从库,而一个从库只能有一个主库。
- 全量复制
- 主节点通过bgsave命令fork一个子进程进行RDB持久化,生成一个dump.rdb的全量快照文件,该过程是非常消耗CPU、内存(页表复制)、硬盘IO的
- 主节点通过网络将RDB文件发送给从节点,对主节点的带宽会带来很大的消耗
- 从节点清空老数据,载入新RDB文件的过程是阻塞的,无法响应客户端的命令,如果从节点执行bgrewriteaof(bg rewrite AOF)也会带来额外的消耗
- 部分复制
- 复制偏移量:执行复制的双方,主从节点分别会维护一个复制偏移量offset,当主从节点回复的偏移量记录不同时,以主节点为准
- 复制积压缓冲区:主节点内部维护了一个固定长度(可以指定,也可临时更改长度)的、先进先出(FIFO)队列作为复制积压缓冲区,将offset后的数据放入队列,每次增量复制时,同步缓存区中的数据即可,避免操作硬盘。当主从节点的offset差距过大超过缓冲区长度时,将无法执行部分复制,只能全量复制
- 服务器运行ID(runid):每个redis节点在启动时自动生成运行id,主节点会将自己的运行id发给从节点,从节点会保存起来,当主从节点断开后重连,从节点根据运行id判断同步方式:
- 若从节点保存的runid与主节点现在的runid相同,说明之前有过同步,主节点会继续尝试使用部分复制(具体看offset和复制积压缓冲区的情况)
- 若runid不同,说明主节点宕机并发生重新选举,断线前同步的redis节点不是当前主节点,只能进行全量复制
作者:彼岸舞
时间:2021 5 5
内容关于:Redis
本文属于作者原创,未经允许,禁止转发