主从复制
单个数据库实例遇到诸如突然断电,还可以从持久化的备份中恢复数据,但是如果系统崩溃了,磁盘损坏了,这样的问题时,保存的数据就完蛋了,所以为了应对这样的问题,Redis也提供了和其他数据库一样的处理办法:**主从复制**
玩主从复制
在同一台机器上,玩儿主从复制,没有多少意义,
方式一,在本地虚拟机上克隆两个已安装的Centos 7系统,分别设置好ip,但windows环境(安装虚拟机的)防火墙关闭不了的话,还是让自动获取吧,因为安装系统时的网段才可被windows(安装虚拟机的环境)防火墙 放行
最先:要安装好虚拟机centos7,关机状态下,右键系统---管理----克隆
然后:克隆好后,三个系统一起启动起来,再设置网络IP
systemctl restart network重启网卡后,还要打开外网络连接
我们这里在3台机器上(云服务器,tenyun-wdinows,qingyu--centos7主服务器,ali-centos7)配置主从复制,需要改的配置:
windows下要修改redis.windows.conf,重启要用cmd来运行该文件
slaveof 主服器ip地址 端口号 //指定本台从redis服务器的主服务器,**主服务器不用配置,一般这个放在文件最尾部,用shift+g定位到尾部**
//相关的配置,可选:
requirepass 123456 //主服务器设置redis登录密码
masterauth 123456 //主服务器其设置密码,从服务器就要设置masterauth来认证,云服务器上是一定要的。
//关注:云从服务器上该密码 与云主服务器上的requirepass的密码相同。
bind 127.0.0.1 //注释也没关系,云服务器有关系,云服务器上是要注释掉的或后面加公网ip和内网ip,没办法本地访问哪个咐的。
云服务器的例子:
bind 127.0.0.1 121.43.32.180 172.26.60.90 //(本机的只要自已的ip,云服务器还要绑上内网IP)
实验的步骤:
1、主服务器不动
2、设置从服务的slaveof
3、主服务器上新建一个key
4、在从服务器上获取这个key的值
5、尝试在从服务器上新建一个key,建不了,默认从服务器是只读的
6、关闭从服务器,在主服务器上新建key
7、重启从服务器,获取刚刚在主服务器上创建的key的值
主从复制的工作原理:
PSYNC命令具有完整重同步(full resynchronization)和部分重同步(partial resynchronization,如增量备份)两种模式:
完整重同步:
1、主服务器需要执行BGSAVE命令来生成RDB文件,这个生成操作会耗费主服务器大量的CPU、内存和磁盘I/O资源;
2、主服务器需要将自己生成的RDB文件发送给从服务器,这个发送操作会耗费主从服务器大量的网络资源(带宽和流量),并对主服务器响应命令请求的时间产生影响;
3、接收到RDB文件的从服务器需要载入主服务器发来的RDB文件,并且在载入期间,从服务器会因为阻塞而没办法处理命令请求。
部分重同步:
部分重同步用于处理断线后重复制情况:
当从服务器在断线后重新连接主服务器时,如果条件允许,主服务器可以将主从服务器连接断开期间执行的写命令发送给从服务器,从服务器只要接收并执行这些写命令,就可以将数据库更新至主服务器当前所处的状态。
部分重同步功能由以下三个部分构成:
1主服务器的复制偏移量(replication offset)和从服务器的复制偏移量;
2主服务器的复制积压缓冲区(replication backlog)
3服务器的运行ID(run ID)。
复制偏移量
执行复制的双方——主服务器和从服务器会分别维护一个复制偏移量:
主服务器每次向从服务器传播N个字节的数据时,就将自己的复制偏移量的值加上N;
从服务器每次收到主服务器传播来的N个字节的数据时,就将自己的复制偏移量的值加上N;
通过对比主从服务器的复制偏移量,程序可以很容易地知道主从服务器是否处于一致状态:
如果主从服务器处于一致状态,那么主从服务器两者的偏
移量总是相同的;相反,如果主从服务 器两者的偏移量并不相同,那么说明主从服务器并未处于一致状态。
假设从服务器A在断线之后就立即重新连接主服务器,并且成功,那么接下来,从服务器将向主服务器发送PSYNC命令,报告从服务器A当前的复制偏移量为10086,
那么这时,主服务器应该对从服务器执行完整重同步还是部分重同步呢?
如果执行部分重同步的话,主服务器又如何补偿从服务器A在断线期间丢失的那部分数据呢?
以上问题的答案都和复制积压缓冲区有关。
复制积压缓冲区
复制积压缓冲区是由主服务器维护的一个固定长度(fixed-size)先进先出(FIFO)队列,默认大小为1MB.
当主服务器进行命令传播时,它不仅会将写命令发送给所有从服务器,还会将写命令入队到复制积压缓冲区里面,如图所示。
-----因此,主服务器的复制积压缓冲区里面会保存着一部分最近传播的写命令,并且复制积压缓冲区会为队列中的每个字节记录相应的复制偏移量,就像下表所示的那样。
当从服务器重新连上主服务器时,从服务器会通过PSYNC命令将自己的复制偏移量offset发送给主服务器,
主服务器会根据这个复制偏移量来决定对从服务器执行何种同步操作:
1.如果offset偏移量之后的数据(也即是偏移量offset+1开始的数据)仍然存在于复制积压缓冲区里面, 那么主服务器将对从服务器执行部分重同步操作;
2.相反,如果offset偏移量之后的数据已经不存在于复制积压缓冲区,那么主服务器将对从服务器执行完整重同步操作
根据需要调整复制积压缓冲区的大小
Redis为复制积压缓冲区设置的默认大小为1MB,如果主服务器需要执行大量写命令,又或者主从服务器断线后重连接所需的时间比较长,那么这个大小也许并不合适。如果复制积压缓冲区的大小设置得不恰当,那么PSYNC命令的复制重同步模式就不能正常发挥作用,因此,正确估算和设置复制积压缓冲区的大小非常重要。
复制积压缓冲区的最小大小可以根据公式second*write_size_per_second来估算:
其中second为从服务器断线后重新连接上主服务器所需的平均时间(以秒计算);
而write_size_per_second则是主服务器平均每秒产生的写命令数据量(协议格式的写命令的长度总和);
例如,如果主服务器平均每秒产生1 MB的写数据,而从服务器断线之后平均要5秒才能重新连接上主服务器,那么复制积压缓冲区的大小就不能低于5MB。为了安全起见,可以将复**制积压缓冲区的大小设为**::::::**2*second\*write_size_per_second**,这样可以保证绝大部分断线情况都能用部分重同步来处理。
至于复制积压缓冲区大小的修改方法,修改配置文件中repl-backlog-size的参数。
服务器运行ID
除了复制偏移量和复制积压缓冲区之外,实现部分重同步还需要用到服务器运行ID(run ID):
每个Redis服务器,不论主服务器还是从服务,都会有自己的运行ID;主从切换-主服务器有错时的操作
运行ID在服务器启动时自动生成,由40个随机的十六进制字符组成,
例如:53b9b28df8042fdc9ab5e3fcbbbabff1d5dce2b3;
当从服务器对主服务器进行初次复制时,主服务器会将自己的运行ID传送给从服务器,
而从服务器则会将这个运行ID保存起来(注意哦,是从服务器保存了主服务器的ID)。
当从服务器断线并重新连上一个主服务器时,从服务器将向当前连接的主服务器发送之前保存的运行ID:
如果从服务器保存的运行ID和当前连接的主服务器的运行ID相同,
那么说明从服务器断线之前复制的就是当前连接的这个主服务器,主服务器可以继续尝试执行部分重同步操作;
相反地,如果从服务器保存的运行ID和当前连接的主服务器的运行ID并不相同,
那么说明从服务器断线之前复制的主服务器并不是当前连接的这个主服务器,
主服务器将对从服务器执行完整重同步操作。
配置高可用和集群
在生产环境中的需求
Redis单实例远远不能提供稳定高效、具备数据冗余和高可用(HA,high availablility)能力的键值存储服务。
持久化和主从复制
可以解决数据冗余备份的问题,但是,如果没有人工的干预,Redis服务器宕机后,是不能自动恢复的。
所以,单纯的主从复制和持久化技术不具备高可用的特性。
“高可用性”(High Availability)
通常来描述一个系统经过专门的设计,从而减少停工时间,而保持其服务的高度可用性。
实现高可用的技术很多,Redis在2.6版本后提供了一个原生支持的技术:
Sentinel(哨兵),利用Sentinel,我们可以轻松地构建具备容错能力的Redis服务。
哨兵
1、Sentinel
----- 哨兵模式就是我们常讲的主从切换技术了,在哨兵模式没出来前,当我们的主服务器宕机了之后,需要人为的去将从机切换成主机去顶一下,在从机中输入命令:slaveof no one ,让 从机 篡位 成为 主机,而主从机的区别就是主机能”写、读“,而从机只能”读“,而人为干预主从切换会造成一段时间内服务不可以使用的问题,于是在Redis2.8之后正式的提供了Sentinel(哨兵模式)架构来解决这个问题,所以哨兵模式也可以理解为:当 某门派大佬驾崩的时候,根据门派内的投票数直接让新老大上位
哨兵模式是一个独立的进程,做为进程,它会独立运行,原理就是通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis主从机.
----sentinel,哨兵的意思,sentinel技术就是给Redis主实例,创建几个哨兵盯着,一般至少需要三个,一旦这些哨兵监测出主服务器宕机了,其中一个哨兵进程就会被选举出来负责推选一个从实例来代替坏掉的主实例,如果配置得当,这些动作都将是计算机自动完成,不需要人工来干预,这样子高可用的特性就出来了。
2、接着上章课程的环境,3台主机,分别配置上redis和sentinel服务。
3、具体配置sentinel
注意:要让所有主从服务器能交互,能被除本机以外的其他计算机访问,
bind 127.0.0.1 可以是注释掉,也可以把要绑定的ip地址追加上去:bind 127.0.0.1 192.168.238.5(云服务器不行的)
操作:
1)在三台服务器上都要做的:复制源码包里的sentinel.conf配置文件,把它复制到安装目录去,这是钟洪发老师安装时没复制了bin和redis.conf到安装处,我一般全都解压到一块了。
//注意这些配置:
port 26379 //默认端口26379
logfile "/usr/local/redis/log/sentinel.log"
sentinel monitor Mymater 192.168.238.4 6379 2
//该行的意思是:监控的master的名字叫做Mymater (自定义),
//地址为192.168.238.4:6379主服务器,行尾最后的一个2代表在sentinel集群中,多少个sentinel认为masters死了,才能真正认为该master不可用了。
daemonize yes
sentinel down-after-milliseconds Mymater 15000
//sentinel会向master发送心跳PING来确认master是否存活,
//如果master在“一定时间范围”内不回应PONG 或者是回复了一个错误消息,
//那么这个sentinel会主观地(单方面地)认为这个master已经不可用了。
//而这个down-after-milliseconds就是用来指定这个“一定时间范围”的,单位是毫秒,默认30秒。
sentinel failover-timeout Mymater 120000
//failover(主备切换)过期时间,当failover开始后,在此时间内仍然没有触发任何failover操作,
//当前sentinel将会认为此次failover失败。默认180秒,即3分钟。
sentinel parallel-syncs Mymater 1
//在发生failover主备切换时,这个选项指定了最多可以有多少个slave同时对新的master进行同步,
//这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,
//就意味着越多的slave因为replication而不可用。
//可以通过将这个值设为 1 来保证每次只有一个slave处于不能处理命令请求的状态。
#sentinel auth-pass Mymater xxxxx
//当一个master配置为需要密码才能连接时,哨兵是通过这个配置来设置主服务器密码的。
2)在三台主机上启动sentinel进程(包括主服务器)
./bin/redis-sentinel ./sentinel.conf
3)使用redis-cli链接哨兵-1,并用info sentinel 查看信息。
#redis-cli -p 6379 -a 123456 info replication //查看服务器情况
# ./bin/redis-cli -p 26379
> info sentinel //查看哨兵状况
windows运行redis-server sentinel.conf出如下错了
4、测试sentinel
1)手动触发故障迁移
链接到哨兵-2上,因为它对应的不是初始化的主服务器: > ./bin/redis-cli -p 26379 -a xxxxx
执行:> sentinel failover mymaster #主从切换
验证原来的主实例,是不是已经不是主从切换了
链接到哨兵-1上: > ./bin/redis-cli -p 6379 -a xxxxx
执行:> info replication
//会看到,从服务器变主服务器了,从服务器减少了一个
role:master
connected_slaves:1
看看日志内容(sentinel.log),新的主服务器哨兵日志
查看新老主服务器的redis配置文件:redis.conf
//可发现,新的主服务器,最后的slaveof 项被删除了,而老的主服器和其它从服务器,都增加了一项(文件的最后行1400多行吧,可shift+G定位到)
replicaof 139.198.11.194 6379 //ip为新主的
新服务器没有slaveof的配置
老服务器多了 REPLIACOF hostname port 会将当前服务器转变为某一服务器的副本服务器
分析试验的内部执行过程:
1、由于故障迁移是手动执行的,所以执行迁移操作之前,不需要寻求其他哨兵的同意,也不需要进行投票决定哨兵-2为leader
2、sentinel就按照上面1中的决定,把哨兵-2从从服务器确认为主服务器
3、sentinel向哨兵-2发出一条命令:slaveof no one(5.0以后:replicaof no one),正式变为主服务器
4、从新分配其他哨兵,让从新的主服务器上复制数据
5、在最后一步里,sentinel更新主服务器的信息,并通过频道sentinel:hello向其他哨兵广播这些 信息,从而让所有客户端获取新主服务器的信息。
配置文件redis.conf和sentinel.conf也会相应的进行更新,以匹配新主服务器的角色
手动容灾执行报异常及处理:经常出现这错误,因为会来来回回干活
(error) NOGOODSLAVE No suitable replica to promote
//具有可能是配置文件没配好,再还有,先后配置了不同的主服务器的问题--先配了它,反悔了,重新配给另一台服务器(原先是从的)。我的是后者。是因为
//Could not create server TCP listening socket *:26379: bind: Address already in use
//处理办法:先查看redis所有进程带‘?’的,再杀光之。再重启redis,sentinel
ps -ef | grep redis
root 15723 1 0 09:34 ? 00:00:03 redis-server *:6379
root 17741 17467 0 10:05 pts/0 00:00:00 grep --color=auto redis
root 25549 1 0 Apr19 ? 00:03:56 redis-sentinel *:26379 [sentinel]
kill -9 15723
kill -9 25549
//重启服务,哨兵
redis-server redis.conf //保证在redis.conf同一个目录下
redis-sentinel sentinel.conf --sentinel //保证在redis.conf同一个目录下
2)模拟主服务器下线
把主服务器上的ridis关掉
在从服务上
执行:> info replication看看剩下的两个从服务器的复制情况信息
分析内部的执行过程:
1、每个哨兵都是定期的向主服务器发送ping命令,如果ping命令超时,对应的服务器被视为下线,注意这里只是主观下线
这里主服务器会被哨兵标注+sdown(主观下线的标记)
2、为了避免虚假警报,标记了+sdown的哨兵,标记后会向其他哨兵发送请求,要求他们检查 对应服务器状态,只有大于sentinel monitor命令中的最后的那个配置的数字(2)的时候,
**才会触发故障迁移,这时服务器被称为客观下线(+odown)**
3、哨兵也将把主服务器标记+sdown和+odown,就开始选举leader,且如果某哨兵被选择为leader的话,就开始执行迁移的步骤
另外,在这里leader的选举过程是这样的:
当一个哨兵标记+odown后,投票开始:哨兵会开始向其他哨兵拉票,每个哨兵都只有一票,当另一个哨兵的拉票请求发来时,如果它以前没有投过票,则响应请求的哨兵,如果已经投给别人了,它会回复“已经把票给了xxx哨兵了”,在这个过程中如果某个哨兵率先获得了(哨兵数/2 + 1)票,那么这个哨兵就是新的leader,如果没有leader当选,上述过程重复。
4)解除哨兵
首先:要关掉主服务器和各从服务器
#redis-cli -p 6379 -a xxxxx shutdown
然后:修改要解除哨兵的从或主服务器的配置文件
//先关闭服务
redis-cli -p 6379 -a xxxxx shutdown
//修改redis.conf,删除或注释掉如下内容
#slaveof 138.15.254.25 6379
//和故障迁移过程产生的
# replicaof 139.125.11.194 6379
#masterauth 123456
//修改sentinel.conf,把如下内容全删除(在文件最后面,可shift+g定位到文件最后面),注释掉sentinel monitor mymater 192.168.238.4 6379 2
sentinel leader-epoch mymaster 4
sentinel known-replica mymaster 124.222.48.147 6379
sentinel known-replica mymaster 60.204.141.192 6379
sentinel known-sentinel mymaster 172.26.60.90 26379
.....................
最后:重启服务就可看到没有主从关系了
#redis-server redis.conf
#redis-cli -p 6379 -a 123456 info replication //查看主从关系