前言
周末两天都在研究这个主从复制和哨兵模式,之前看文章觉得还是很简单的,但是一实践就遇到了很多坑🤔,浪费了大把的时间,头发都掉了好几根,周日弄完后整理下,分享给大家,搭建的时候少走点弯路😁。
这篇文章主要讲的是主从复制,什么是主从复制?主从复制原理是什么?主从复制集群如何搭建
本文使用 docker 部署搭建的,使用了2台阿里云服务器,这里还是推荐大家不要在一台电脑上搭建,因为一台电脑和两台电脑,踩的坑还是有区别的 ψ(*`ー´)ψ,多台电脑踩得坑比较全面୧(﹒ᴗ﹒)୨,所以不要怕麻烦,没有云服务器的可以开两台虚拟机
主从复制
简介
主从复制就是一主多从,从节点(slave)同步主节点(master)数据(主节点写入数据时,会同步复制到从节点),主节点主要负责写入,从节点负责数据读取,无法写入,当然这是一个配置项,是可以修改(不过一般不推荐),下面详细的讲一下
主从复制的作用(概念性东西,需要背一背)✨
- 负载均衡,主节点负责写,从节点负责读,分摊服务器压力
- 实现了数据的热备份,是持久化之外的一种数据冗余方式
- 高可用,主节点发生故障的时候,从节点可以继续提供服务(查询数据)
- 哨兵模式就是建立在主从复制之上的,所以学习哨兵模式肯定要先学习主从复制
主从复制的优点(概念性东西,需要背一背)✨
- 一个 Master 可以同步多个 Slaves
- Slave 同样可以接受其它 Slaves 的连接和同步请求,这样可以有效的分载 Master 的同步压力。因此我们可以将 Redis 的 Replication 架构视为图结构
- Master Server是以非阻塞的方式为Slaves提供服务。所以在Master-Slave同步期间,客户端仍然可以提交查询或修改请求
- Slave Server同样是以非阻塞的方式完成数据同步。在同步期间,如果有客户端提交查询请求,Redis则返回同步之前的数据
- 为了分载Master的读操作压力,Slave服务器可以为客户端提供只读操作的服务,写服务仍然必须由Master来完成。即便如此,系统的伸缩性还是得到了很大的提高
- 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离
主从复制的缺点(概念性东西,需要背一背)✨
- 当主节点或从节点宕机以后,在恢复节点以前,都会对读写业务逻辑造成影响
- Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费
- Redis 主从复制是通过全量复制的,复制的时候主节点会fork出一个子进程,对当前数据做一份快照,然后同步给从节点,如果数据特别多的话,生成的快照就比较大,复制过程就需要保证有足够的内存,对集群的服务能力会产生较大的影响(这个复制过程是在从机新加入集群或者从机和主机网络断开重连时都会进行,也就是网络波动都会造成主机和从机间的一次全量的数据复制,这对实际的系统运营造成了不小的麻烦)
主从复制工作流程✨
这一块大概知道一些,能简单讲讲就可以了
主从复制大概有3个阶段
一、建立链接
- 从节点配置 master 的 ip 和 port,发送 slaveof 命令建立 slave 到 master 的链接,让 master 保存识别 slave,
- master接收到 slaveof 命令,识别响应
- 从机保存 master 的 ip 和 port
- 从机根据保存的 ip 和 port 创建 socket 连接
- 从机 周期发送命令 ping
- 主机响应 ping
- 从机发送指令 auth password 鉴权
- 验证授权
- 从机发送自己端口信息
- 主机保存从机节点信息
至此连接建立成功
二、数据同步
在网上找了一张画的很棒的流程图,根据这张图来讲一下,同步数据的流程吧
-图片来源于网络
首次同步是全量同步,后面再同步就是增量同步了,就是通过偏移量,来确定上次同步到哪里了,这次从哪里继续同步,其实在 redis2.8 之前是没有增量同步的,由于效率等问题,在2.8之后增加了增量同步。 当宕机或者网络波动的时候都会触发同步
第一次同步
- 第一步一般就是上面那个建立连接
- 如果是第一次复制,从机发送PSYNC ? -1命令,表示进行完整数据同步
- 然后主服务器会返回 主服务器ID 和 偏移量(主库复制进度)
- 从机收到响应后记录这两个参数
- 主机会在后台执行 BGSAVE 命令,生成RDB文件,再把文件发给从库
- 从库收到RDB文件以后,会清空当前数据库,加载 RDB 文件
非首次同步
- 像主机发送 PSYNC [主服务器ID] [偏移量] 命令,携带的两个参数是第一次同步返回回来的(偏移量就是定位上一次复制到哪里了,然后同步偏移量后面所有的数据)
- 主机收到命令之后,找到相应同步位置,给从服务器发送 +CONTINUE 命令,表示将于从服务器执行部分同步操作,之后主服务器会将保存在复制积压缓冲区对应 复制偏移量之后的所有数据发送给从服务器,但是如果找不到偏移量之后的数据,就会进行完整同步,这样就可以让从服务器达到和主服务器一致的状态。
三、命令传播
当同步完成后,然后就可能有写命令进来,当有写命令的时候,也是这样同步的吗?
答案:不是
当主机写入数据的时候,并不会走同步这个逻辑,如果走同步流程的话是非常耗时的,完成同步后,会维护一个网络连接,当再写入数据的时候,把写入的命令发给从机,让从机直接执行命令,来达到同步数据这么一个效果。
拓展
为什么主库间的数据复制同步不使用AOF?
有三方面原因:
- RDB文件是经过二进制压缩的,文件很小,这样主从库间传输就很快。
- 从库加载RDB文件速度很快,而AOF日志还要逐行命令执行,速度很慢。
- 假设使用AOF,那就必须打开AOF,Redis默认是不开启AOF的,可能会影响Redis性能。
如果从机比较多的话,进行同步会不会影响主机效率
Redis 提供主-从-从模式将主库生成RDB和传输RDB的压力,以级联的方式分散到从库上。
简单的说就是构建父子从库结构,主给父从机,父从再给子从。
直接在从库执行命令:replicaof 所选从库的IP 6379,就可以设置从库的父从库了。
总结
- 主从复制就是主机和从机组成一个集群通过同步及命令传播等方式保证数据一致
- 主机负责写,主机负责读,分担服务器读写压力
部署redis主从复制
部署
redis配置下载
下载 redis 配置文件😎
wget -c http://download.redis.io/redis-stable/redis.conf
然后就是 pull redis的镜像,直接获取新版的就可以了😎
docker pull redis
修改配置文件,如果设置了密码,一定要记得在从服务器配置 masterauth,从服务器连接主服务器会校验密码的,配置项很简单,改了一下几个配置就可以了
# 使得Redis服务器可以跨网络访问
bind 0.0.0.0
# 设置密码
requirepass "123456"
# 指定主服务器,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
slaveof 192.168.1.2 6379
# 主服务器密码,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
masterauth 123456
# 创建以下两个目录,docker-compose会用到,当然可以自定义,改下下面的docker-compose文件就可以了
/root/docker-data/redis/config # 配置文件存放目录
/root/docker-data/redis/data # 数据存放目录
启动docker,我这里采用的是 docker-compose 部署,分别在两台机器上执行,然后就ok了
# master
version: "3.2"
services:
redis:
image: redis:latest
container_name: redis-master
restart: always
network_mode: host
volumes:
- /etc/localtime:/etc/localtime:ro
- /root/docker-data/redis/config:/usr/local/etc/redis/ # 配置挂载到磁盘
- /root/docker-data/redis/data:/data # 数据挂载到磁盘挂载到磁盘
command: redis-server /usr/local/etc/redis/redis.conf
# slave
version: "3.2"
services:
redis:
image: redis:latest
container_name: redis-slave
restart: always
ports:
- 6379:6379
- 26379:26379
volumes:
- /etc/localtime:/etc/localtime:ro
- /root/docker-data/redis-slava/config/:/usr/local/etc/redis/
- /root/docker-data/redis-slava/data:/data
command: redis-server /usr/local/etc/redis/redis.conf
进入docker 容器,查看信息
# 进入主节点容器
docker exec -it redis-master bash
# 登录redis client
redis-cli -a 123456
# info replication 查看状态
127.0.0.1:6379> info replication
# Replication
role:master # 当前角色
connected_slaves:1 # 已经有一个从节点连接成功
slave0:ip=192.168.1.3,port=6379,state=online,offset=661,lag=0
# 进入从机执行同样命令
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.1.2
master_port:6379
从节点连接不上主节点问题排查
基本上就是以下几种情况,因为我就犯了😂:
- bind 0.0.0.0 没配置
- 没对外暴露端口,关闭防火墙或者配置规则可以解决,云服务器需要配置安全组
- 从机配置文件未配置主机密码(redis密码)
好了,这次分享到这里了,有什么问题,欢迎大家提问