博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NoSQL之【Redis】学习(四):复制说明
阅读量:6696 次
发布时间:2019-06-25

本文共 8255 字,大约阅读时间需要 27 分钟。

       Redis目前支持复制,不支持(在开发中)。Redis复制流程概述:Redis的复制功能是完全建立在之前我们讨论过的基于内存快照的持久化策略基础上的,也就是说无论你的持久化策略选择的是什么,只要用到了Redis的复制功能,就一定会有内存快照发生,即使主没有开启了snapshot持久,也会有rbd文件生成(原因下面说明)。那么首先要注意你的系统内存容量规划。

Redis复制流程在Slave和Master端各自是一套状态机流转,涉及的状态信息是:

整个流程过程如下:    Slave端在配置文件中添加了slave of指令,于是Slave启动时读取配置文件,初始状态为REDIS_REPL_CONNECT。    Slave端在定时任务serverCron(Redis内部的定时器触发事件)中连接Master,发送sync命令,然后阻塞等待master发送回其内存快照文件(最新版的Redis已经不需要让 Slave阻塞)。    Master端收到sync命令简单判断是否有正在进行的内存快照子进程,没有则立即开始内存快照,有则等待其结束,当快照完成后会将该文件发送给Slave端。    Slave端接收Master发来的内存快照文件,保存到本地,待接收完成后,清空内存表,重新读取Master发来的内存快照文件,重建整个内存表数据结构,并最终状态置位为 REDIS_REPL_CONNECTED状态,Slave状态机流转完成。    Master端在发送快照文件过程中,接收的任何会改变数据集的命令都会暂时先保存在Slave网络连接的发送缓存队列里(list数据结构),待快照完成后,依次发给Slave,之后 收到的命令相同处理,并将状态置位为 REDIS_REPL_ONLINE。

整个复制过程完成,流程如下图所示:

 

Redis复制机制的缺陷:

      从上面的流程可以看出,Slave从库在连接Master主库时,Master会进行内存快照,然后把整个快照文件发给Slave,也就是没有象MySQL那样有复制位置的概念,即无增量复制,这会给整个集群搭建带来非常多的问题。
比如一台线上正在运行的Master主库配置了一台从库进行简单读写分离,这时Slave由于网络或者其它原因与Master断开了连接,那么当Slave进行重新连接时,需要重新获取整个Master的内存快照,Slave所有数据跟着全部清除,然后重新建立整个内存表,一方面Slave恢复的时间会非常慢,另一方面也会给主库带来压力。
所以基于上述原因,如果你的Redis集群需要主从复制,那么最好事先配置好所有的从库,避免中途再去增加从库

注意:

Redis的复制功能没有增量复制,每次重连都会把主库整个内存快照发给从库,所以需要避免向在线服务的压力较大的主库上增加从库。

Redis的复制由于会使用快照持久化方式,所以如果你的Redis持久化方式选择的是日志追加方式(aof),那么系统有可能在同一时刻既做aof日志文件的同步刷写磁盘,又做快照写磁盘操作,这个时候Redis的响应能力会受到影响。所以如果选用aof持久化,则加从库需要更加谨慎。

以上来自中的复制介绍。

按照 这篇文章装好Redis。配置从Redis,很简单,只需要修改配置文件(redis_slave.conf)的几个参数:

#Pid 文件 pidfile /var/run/redis2.pid#端口port 6380#套接字文件unixsocket /tmp/redis2.sock#日志文件logfile /var/log/redis/redis2.log#持久化文件目录dir /var/lib/redis2 #从配置选项# slaveof 
slaveof 192.168.200.202 6379

指定配置文件启动后(/usr/local/bin/redis-server /etc/redis_slave.conf),日志信息如下:

1 [22108] 27 May 11:53:00.495 * MASTER <-> SLAVE sync started2 [22108] 27 May 11:53:00.498 * Non blocking connect for SYNC fired the event.3 [22108] 27 May 11:53:00.498 * Master replied to PING, replication can continue...4 [22108] 27 May 11:53:00.563 * MASTER <-> SLAVE sync: receiving 18 bytes from master5 [22108] 27 May 11:53:00.563 * MASTER <-> SLAVE sync: Loading DB in memory6 [22108] 27 May 11:53:00.563 * MASTER <-> SLAVE sync: Finished with success

从Redis已经完成,测试replication:

主:192.168.200.25 6379

从:192.168.200.202 6379

#测试前检查MS一致性:root@zhoujy:~# redis -h 192.168.200.25redis 192.168.200.25:6379> keys *(empty list or set) redis 192.168.200.25:6379> root@zhoujy:~# redis -h 192.168.200.202redis 192.168.200.202:6379> keys *(empty list or set)redis 192.168.200.202:6379> #测试同步root@zhoujy:~# redis -h 192.168.200.25redis 192.168.200.25:6379> set name zhoujinyiOKredis 192.168.200.25:6379> set sex manOKredis 192.168.200.25:6379> set age 27OKredis 192.168.200.25:6379> saveOKredis 192.168.200.25:6379> keys *1) "name"2) "age"3) "sex"redis 192.168.200.25:6379> root@zhoujy:~# redis -h 192.168.200.202redis 192.168.200.202:6379> keys *1) "age"2) "sex"3) "name"redis 192.168.200.202:6379>

上面结果显示,数据已经从M同步到了S。

注意:创建复制时,可以很清楚的看到Master上仅在第一次做Slave同步时创建了dump.rdb文件,之后就通过增量传输命令的方式给Slave了,rdb文件没有再增大。而Slave的RDB和AOF 随着数据的增加而增大,并且AOF的增长速度大于RDB。

在上一篇文章 里面已经说了:

利用Replication机制来弥补aof、snapshot性能上的不足,达到了数据可持久化。即Master上Snapshot和AOF都不做,来保证Master的读写性能,而Slave上则同时开启Snapshot 和AOF来进行持久化,保证数据的安全性

既然Master上持久化不做,只在Slave上做持久化,那Master崩溃数据就会全部丢失,那如何恢复呢?接下来进行测试:

Master的配置:关闭自动持久化

#save 900 1#save 300 10#save 60 10000appendonly no

Slave的配置:开启自动持久化

save 900 1save 300 10save 60 10000appendonly yesappendfilename appendonly.aofappendfsync everysec no-appendfsync-on-rewrite yes auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb

这些配置的意思请看,重启主从服务器,使配置生效。

测试:

# 检查配置是否生效redis 192.168.200.25:6379> keys *(empty list or set)redis 192.168.200.25:6379> CONFIG GET save1) "save"2) ""redis 192.168.200.25:6379> CONFIG GET append*1) "appendonly"2) "no"redis 192.168.200.202:6379> CONFIG GET save1) "save"2) "900 1 300 10 60 10000"redis 192.168.200.202:6379> CONFIG GET append*1) "appendonly"2) "yes"3) "appendfsync"4) "everysec"#检查同步情况root@zhoujy:~# redis -h 192.168.200.25redis 192.168.200.25:6379> keys *(empty list or set)redis 192.168.200.25:6379> root@zhoujy:~# redis -h 192.168.200.202redis 192.168.200.202:6379> keys *(empty list or set)redis 192.168.200.202:6379> root@zhoujy:~# redis -h 192.168.200.25redis 192.168.200.25:6379> set name zhoujinyiOKredis 192.168.200.25:6379> set sex manOKredis 192.168.200.25:6379> set age 27OKredis 192.168.200.25:6379> keys *1) "age"2) "name"3) "sex"redis 192.168.200.25:6379> root@zhoujy:~# redis -h 192.168.200.202redis 192.168.200.202:6379> keys *1) "name"2) "age"3) "sex"#以上测试已经证明同步成功
#M崩溃恢复:redis 192.168.200.25:6379> INFO               #通过INFO命令查看M的信息# Server……# Clients……# Memory……# Persistencerdb_changes_since_last_save:3                #离最后一次保存改变了3个keyaof_enabled:0                                #关闭了aof持久# Stats……# Replicationrole:master                                  #该实例为主服务器connected_slaves:1                           #有一个从服务器连接slave0:192.168.200.202,6379,online           #从服务器的信息          # CPU……# Keyspacedb0:keys=3,expires=0                         #该实例有3个key #模拟主库异常崩溃:~# kill -9 1647root@zhoujy:~# /etc/init.d/redis-server start #崩溃后启动Starting redis-server: redis-server.root@zhoujy:~# redis -h 192.168.200.25#M崩溃恢复:redis 192.168.200.25:6379> INFO               #通过INFO命令查看M的信息# Server……# Clients……# Memory……# Persistencerdb_changes_since_last_save:0                #离最后一次保存改变了0个keyaof_enabled:0                                #关闭了aof持久# Stats……# Replicationrole:masterconnected_slaves:1slave0:192.168.200.202,6379,online           #和之前信息一样,那是不是数据也正常呢?            # CPU……# Keyspace                                   #没有key信息,数据丢失。---不正常,丢失了redis 192.168.200.25:6379> keys * (empty list or set)                          #确实M上已经没有数据redis 192.168.200.25:6379> root@zhoujy:~# redis -h 192.168.200.202      #进入从库看看是否正常redis 192.168.200.202:6379> keys *         (empty list or set)                          #S上也没有数据了?Why?

Slave上数据也随着丢失的原因是上面提到过的一个复制的缺陷引起的:

Slave由于网络或者其它原因与Master断开了连接,那么当Slave进行重新连接时,需要重新获取整个Master的内存快照,Slave所有数据跟着全部清除,然后重新建立整个内存表。上面的情况是因为这时Master已经丢失了数据,快照是空的,直接通过空的快照传给Slave,导致Slave的数据也被清空了。那如何避免呢?

继续测试

# 从上面的 “模拟异常崩溃” 开始测试
#模拟异常崩溃root@zhoujy:/var/lib/redis# /etc/init.d/redis-server stop #关闭主RedisStopping redis-server: redis-server.root@zhoujy:~# redis -h 192.168.200.202       #查看slave的状态redis 192.168.200.202:6379> INFO# Server……# Clients……# Memory……# Persistence……# Stats……# Replicationrole:slavemaster_host:192.168.200.25master_port:6379master_link_status:down                      # Master已经不可访问了(down)。Slave依然运行良好,并且保留有AOF与RDB文件。master_last_io_seconds_ago:-1master_sync_in_progress:0master_link_down_since_seconds:160slave_priority:100slave_read_only:1connected_slaves:0# CPU……# Keyspacedb0:keys=3,expires=0                         #看到从上还保留3个key#我们将通过Slave上保存好的AOF与RDB文件来恢复Master上的数据。把Slave上的RDB文件复制到主上。(保证文件名和配置文件一致) 1,首先,将Slave上的同步状态取消,避免主库在未完成数据恢复前就重启,进而直接覆盖掉从库上的数据,导致所有的数据丢失(上面测试出现的情况) redis 192.168.200.202:6379> CONFIG GET slaveof  #查看同步配置1) "slaveof"2) "192.168.200.25 6379"redis 192.168.200.202:6379> SLAVEOF NO ONE      #断开同步OKredis 192.168.200.202:6379> INFO                #断开同步成功# Replicationrole:masterconnected_slaves:02,然后,把RDB文件复制到指定地方: cp dump.rdb  /var/lib/redis/zhoujy.rdb        #注意相关权限(redis)/var/lib/redis# /etc/init.d/redis-server start    #启动主RedisStarting redis-server: redis-server.查看下日志里面的记录:“* DB loaded from disk: 0.000 seconds”,主已经从RDB文件里面恢复。进入查看下: redis 192.168.200.25:6379> INFO# Keyspacedb0:keys=3,expires=0                          #主恢复了3个kyeredis 192.168.200.25:6379> keys *             #数据已恢复1) "sex"2) "age"3) "name3,最后,重新开启主从: redis 192.168.200.202:6379> SLAVEOF 192.168.200.25 6379   #从重新把主的内存快照取到,清空本地内存,重放取到的内存快照。 OKredis 192.168.200.202:6379> INFO# Replicationrole:slavemaster_host:192.168.200.25master_port:6379master_link_status:upmaster_last_io_seconds_ago:1master_sync_in_progress:0slave_priority:100slave_read_only:1connected_slaves:0

      通过此次实验,我们通过在Slave上启的快照,来保证了数据,恢复了Mater。根据上篇持久性介绍的文章,在大数据量的前提下,AOF的增长要比RDB快很多。所以要是对数据的一致性要求不是很高,允许丢失一些数据的话,建议只在从上开启Snapshot来进行持久化,不开启AOF(?)。同时可以考虑将save中的频率调高一些或者调用一个计划任务来进行定期bgsave的快照存储,来尽可能的保障本地化数据的完整性。样的架构下,如果仅仅是Master挂掉,Slave完整,数据恢复可达到100%;如果Master与Slave同时挂掉的话,数据的恢复也可以达到一个可接受的程度。当然不允许数据丢失的话,就要开启AOF了,不过最好新建的时候就开启,不要中途开启,上篇有说明。

总结:

       因为在Redis中,持久化和复制的重连都需要一定的开销,极端情况下这个开销会导致数据库的不可用,所以根据自身的情况,建立合适的主从和持久化方案,可以让Redis和系统更稳定的运行。

转载地址:http://oapoo.baihongyu.com/

你可能感兴趣的文章
201671010128 2017-09-17《Java程序设计》之步步深入面向对象
查看>>
Linux内核在I386架构下的内存管理
查看>>
打包文件 MANIFEST.MF 功能详解
查看>>
构建vue单页应用(一)
查看>>
最小公倍数
查看>>
HDOJ_ACM_Can you find it?
查看>>
SpringMVC-常用的注解
查看>>
羊车门问题
查看>>
【总结整理】overflow: auto/hidden;清除自己
查看>>
用substr()截取中文出现乱码的解决方法
查看>>
Java练习 SDUT-2400_高中数学?
查看>>
UGUI组件之InputField 组件简单笔记(输入栏 输入框 )
查看>>
java-随学随记之基础篇
查看>>
Linux 统计文件夹,文件数量的命令
查看>>
js 中的 exec( )方法
查看>>
8.常量如何取值
查看>>
spring hibernate实现动态替换表名(分表)
查看>>
精通ArrayList,关于ArrayList你想知道的一切
查看>>
KeyStore和TrustStore
查看>>
iOS - WKWebView加载不受信任的https (因用到IP地址加端口号去请求数据)
查看>>