Redis主从复制搭建、哨兵搭建、集群搭建全过程
作者:祁仙森
主从复制
此模式的优势:读写分离,性能扩展;容灾快速恢复
搭建步骤(例子:一主两从)
首先定义一个目录便于后期区分主从,单节点服务,集群模式。我就在//home/scene/installPackage目录下定义了一个redis-master-slave目录
将redis.conf拷贝一份到刚刚的redis-master-slave目录下
cp /etc/redis.conf /home/scene/installPackage/redis-master-slave
配置一主两从,创建3个配置文件:redis6379.conf、redis6380.conf、redis6381.conf
先关闭aof开关,将公共的redis.conf配置文件里的appendonly的值改为no即可;appendonly不关也可以,或者换名字即可
在三个文件中写入配置内容
首先第一个,vi redis6379.conf
# 首先引入公共部分配置 include /home/scene/installPackage/redis-master-slave/redis.conf # 配置pid文件 pidfile /var/run/redis_master_slave_6379.pid # 配置启动的端口 port 6379 # RDB文件名称,保存在当前目录下了 dbfilename dump_master_slave_6379.rdb
参照redis6379.conf配置文件再配置redis6380.conf、redis6381.conf即可,快速的方式
cp redis6379.conf redis6380.conf ##然后使用vi编辑,此处无需实际编辑,输入 :%s/6379/6380 即可全局将6379替换成6380,省去时间,然后再保存即可
启动服务,分别执行(在/home/scene/installPackage/redis-master-slave目录下)
redis-server redis6379.conf redis-server redis6380.conf redis-server redis6381.conf
使用客户端连接其中服务redis-cli -p 6379,随便哪个端口的服务都是,在客户端使用指令info replication查看主从效果,发现都是独立的主服务
在从机上(比如此处选择6379为主节点,6380,6381为从节点)执行slaveof 127.0.0.1 6379,即可实现主从模式,再执行info replication查看信息,便可看到主从信息
注意,主从一旦搭建完成,主节点可读可写,从节点只能读取,不能写入,写入会报错
永久化实现6379为主节点,其余两个为从节点,配置刚刚的redis6379.conf、redis6380.conf、redis6381.conf
redis6379.conf的内容
# 首先引入公共部分配置 include /home/scene/installPackage/redis-master-slave/redis.conf #任意ip都可以连接 bind 0.0.0.0 #关闭保护,允许非本地连接 protected-mode no #进程守护文件,存放该服务进程号相关信息文件 pidfile /var/run/redis_master_slave_6379.pid # 配置启动的端口 port 6379 # RDB文件名称,保存在当前目录下了 dbfilename dump_master_slave_6379.rdb #日志文件保存地址 logfile "/var/run/redisms/log/6379/redis_master_slave_6379.log" #开启aof日志形式 appendonly yes #requirepass 密码设置可以不设置,不配置的话,密码没有,配置的话密码是有的 requirepass 123456
redis6380.conf的内容
# 首先引入公共部分配置 include /home/scene/installPackage/redis-master-slave/redis.conf #任意ip都可以连接 bind 0.0.0.0 #关闭保护,允许非本地连接 protected-mode no #进程守护文件,存放该服务进程号相关信息文件 pidfile /var/run/redis_master_slave_6380.pid # 配置启动的端口 port 6380 # RDB文件名称,保存在当前目录下了 dbfilename dump_master_slave_6380.rdb #日志文件保存地址 logfile "/var/run/redisms/log/6380/redis_master_slave_6380.log" #主信息,格式应该是replicaod <masterip> <materport> replicaod 127.0.0.1 6379 #如果主节点开启了密码的话,这儿要配置密码masterauth <master-password> masterauth 123456 #开启aof日志形式 appendonly yes #requirepass 密码设置可以不设置,不配置的话,密码没有,配置的话密码是有的 requirepass 63806380
redis6381.conf配置内容
# 首先引入公共部分配置 include /home/scene/installPackage/redis-master-slave/redis.conf #任意ip都可以连接 bind 0.0.0.0 #关闭保护,允许非本地连接 protected-mode no #进程守护文件,存放该服务进程号相关信息文件 pidfile /var/run/redis_master_slave_6381.pid # 配置启动的端口 port 6381 # RDB文件名称,保存在当前目录下了 dbfilename dump_master_slave_6381.rdb #日志文件保存地址 logfile "/var/run/redisms/log/6381/redis_master_slave_6381.log" #主信息,格式应该是replicaod <masterip> <materport> replicaod 127.0.0.1 6379 #如果主节点开启了密码的话,这儿要配置密码masterauth <master-password> masterauth 123456 #开启aof日志形式 appendonly yes #requirepass 密码设置可以不设置,不配置的话,密码没有,配置的话密码是有的 requirepass 63816381
此时若配置了密码的话客户端连接指令
redis-cli -p 6379 -a 123456 redis-cli -p 6380 -a 63806380 redis-cli -p 6381 -a 63816381
主从模式服务故障
一主二从情形
情形一:某个从服务器挂掉
若有情形,主从复制模式下(不是永久的在配置文件定义6379为主节点),上述环境,若都正常后,突然6380节点服务挂了,而后又有6379redis数据进来,此时问题就来了
- 第一个问题,重启6380端口服务,6380不是6379的从服务,只有再在6380的客户端使用指令
slaveof 127.0.0.1 6379可以再次使6379变成master服务 - 第二个特点,当从节点6380服务器挂掉之后在重启,然后指向为6379的从服务的时候,挂掉期间的数据还是和主节点一样的,不会出现数据不同步的情形(也就是说数据还是同步过来的)
情形二:主节点挂掉
当主服务节点挂掉之后,从服务节点不做任何操作,只是在info replication知道主节点挂了,不会上位
薪火相传
6379为6381的master,6381为6380的master,类似6379—>6381—>6380,突然6381挂了,6381数据就不是实时的了,和上面的一主二从模式类似的问题特点
反客为主
当主节点的突然挂了之后,可以手动的使用指令slaveof no one实现某一节点变为主节点
若6379为master,6380、6381两个都是6379的从节点,突然6379挂了,然后设置6380为主节点,在6380客户端设置slaveof no one,6380位孤立的主节点,6381还是6379的主节点,除非在6381的客户端设置slaveof 127.0.0.1 6380的时候6381才变成6380的从节点
主从复制原理
- 当从服务连接上主服务之后,从服务向主服务发送进行数据同步信息
- 主节点接收到从节点发送过来的同步信息,把主服务器数据持久化,rdb文件,把rdb文件发送从服务器,从服务器拿到rdb进行文件读取
- 每次主服务器进行写操作之后,和从服务器进行数据的同步
从服务器只有第一次是主动去想主服务,后续出现数据操作,都是主服务同步给从服务的
也就是第一次是全量复制(slave服务在接收到master数据库文件数据后,将其存盘并加载到内存中),后续是增量复制(Master后续将新的所有收集到的修改命令依次传给slave完成同步)
哨兵模式
搭建流程
在上面搭建主从模式的基础上继续配置,在/home/scene/installPackage/redis-master-slave目录下,新建sentinel.conf文件(文件名必须是这个),填写以下内容
sentinel monitor mymaster 127.0.0.1 6379 1
其中mymaster为监控对象起的服务器名称,1为至少有多少个哨兵同一迁移的数量
启动哨兵模式,启动使用指令,前提是在已搭建6379为master,6380、6381为slave的节点的主从基础上,再执行redis-sentinel sentinel.conf即可

假设此时6379服务挂了,哨兵服务会有一段时间间隔的才会监控到主服务挂了,然后选举6380、6381的节点去竞争当选主服务,假设6381成功被选举成为主节点后,那么6380以及重启后的6379都会是6381的从节点,注意6379重启后会有一段延时才会自动成为6381的从节点,6380在6381被成功选举成主节点后,6380也会有一定时间间隔才成为6381的从节点
选举的条件依次为:
- 选择优先级靠前的(这个在redis.conf中的replica-prority的值有关,默认100,值越小优先级越高)
- 选择偏移量最大的(偏移量指源主机数据最全的)
- 选择runid最小的从服务(每个redis实例启动后都会随机生成一个40位的runid)
缺陷——复制延迟
由于所有的写操作都是先在master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重
Redis集群
集群发展及特点:早起的Redis版本是通过代理主机的模式搭建集群的,而Redis3版本通过去中心化实现集群的搭建
搭建步骤
- 为了便于区分上面的主从的搭建环境,在/home/scene/installPackage目录下创建目录redis-cluser来搭建集群。创建集群模式案例:6379主、6389从;6380主、6390从;6381主、6391从
- 编写配置文件redis6379.conf
# 首先引入公共部分配置 include /home/scene/installPackage/redis-cluster/redis.conf # 设置可连接ip,此处我就只指定本机的了,0.0.0.0是都可以访问,但是安全不高 bind 127.0.0.1 170.100.131.41 # 配置pid文件,pid之前的文件路径必须手动生成,否则启动没有效果,ps -ef |grep redis会没有看到后台pid pidfile "/var/run/redis_cluster_6379.pid" # 配置启动的端口 port 6379 # RDB文件名称 dbfilename "dump_cluster_6379.rdb" # 开启集群模式 cluster-enabled yes # 设定节点配置文件名 cluster-config-file nodes6379.conf # 设定节点失联时间,超过该时间(毫秒),集群自动进行主从切换 cluster-node-timeout 15000
然后复制文件更改后面的配置
- 启动各服务
redis-server redis6379.conf redis-server redis6380.conf redis-server redis6381.conf redis-server redis6389.conf redis-server redis6390.conf redis-server redis6391.conf

将六个节点合成一个集群
组合之前,确保所有Redis实例启动后,配置的node-XXXX.conf都正常生成
5和6版本已经不需要ruby环境,已经将redis-trib.rb的功能集成到了redis-cli,而5之前的版本搭建集群需要ruby环境
进入到最初解压后然后make的目录下,我的是/home/scene/installPackage/redis-6.2.6,
然后进入到该目录的src目录下,里面有个redis-cli文件,在该目录下,执行指令,ip地址一定要实际地址
redis-cli --cluster create --cluster-replicas 1 170.100.131.41:6379 170.100.131.41:6380 170.100.131.41:6381 170.100.131.41:6389 170.100.131.41:6390 170.100.131.41:6391
replicas 1表示采用最简单的方式配置集群,一台主机,一台丛从机,正好三组
若执行的时候出现Could not connect to Redis at xx.xx.xx.xx:xx: Connection refused的时候,先查看配置文件的bind是否开放此ip,再检查还有防火墙端口,执行效果如下,我这儿生成一个All 16384 slots covered.

上面的slots插槽的用处

一个redis集群包含16384个插槽(hash slot),数据库中的每个键都属于这16384个插槽的其中一个;集群使用公式CRC16(key)%16384来计算键key属于哪个槽
集群的方式在客户端连接,使用指令,在普通的连接指令加-c参数即可
redis-cli -c -p 6379
连接成功后使用指令cluster nodes查看集群信息

Redis cluster如何分配这六个节点
一个集群至少需要三个主节点
选项--cluster-replicas 1表示希望为集群中的每个主节点创建一个从节点
分配原则尽量保证每个主数据库运行在不通的ip地址,每个从库和主库不在一个ip地址上
关于slot槽的分配的情况说明


集群下查看某个键的插槽的值
cluster keyslot k1
查看某个插槽的键的个数,注意一定要切换到主节点对应的插槽区间的那个节点去查询,不然会返回0
cluster countkeysinslot 12706

故障恢复
情形一:如上集群6379主、6389从;6380主、6390从;6381主、6391从,有6379的主节点服务突然挂了,就集群中就将对应的6389由从节点转变为主节点,当6379再启动的时候就会变成6389的从节点
情形二:当突然6379主节点和其对应的6389从节点都挂了的话,会根据redis.conf配置文件中的cluster-require-full-coverage的值来判定,如果值为yes,那么整个集群都会挂掉;如果值为no,也就是对应挂了的该段槽范围(此次案例中的启动是0-5460的槽值)不能正常提供服务,其余的还是正常的
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
