设为首页 收藏本站
查看: 968|回复: 0

[经验分享] NoSQL之【Redis】学习(四):复制说明

[复制链接]

尚未签到

发表于 2015-7-20 09:20:52 | 显示全部楼层 |阅读模式
     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。
  整个复制过程完成,流程如下图所示:
DSC0000.jpg
  
  Redis复制机制的缺陷:
      从上面的流程可以看出,Slave从库在连接Master主库时,Master会进行内存快照,然后把整个快照文件发给Slave,也就是没有象MySQL那样有复制位置的概念,即无增量复制,这会给整个集群搭建带来非常多的问题。
比如一台线上正在运行的Master主库配置了一台从库进行简单读写分离,这时Slave由于网络或者其它原因与Master断开了连接,那么当Slave进行重新连接时,需要重新获取整个Master的内存快照,Slave所有数据跟着全部清除,然后重新建立整个内存表,一方面Slave恢复的时间会非常慢,另一方面也会给主库带来压力。
所以基于上述原因,如果你的Redis集群需要主从复制,那么最好事先配置好所有的从库,避免中途再去增加从库。
  注意:
  Redis的复制功能没有增量复制,每次重连都会把主库整个内存快照发给从库,所以需要避免向在线服务的压力较大的主库上增加从库。
Redis的复制由于会使用快照持久化方式,所以如果你的Redis持久化方式选择的是日志追加方式(aof),那么系统有可能在同一时刻既做aof日志文件的同步刷写磁盘,又做快照写磁盘操作,这个时候Redis的响应能力会受到影响。所以如果选用aof持久化,则加从库需要更加谨慎。
  以上来自Redis复制与可扩展集群搭建中的复制介绍。
  按照 NoSQL之【Redis】学习(一):安装说明 这篇文章装好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 started
2 [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 master
5 [22108] 27 May 11:53:00.563 * MASTER  SLAVE sync: Loading DB in memory
6 [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.25
redis 192.168.200.25:6379> keys *
(empty list or set)
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)
redis 192.168.200.202:6379>
#测试同步
root@zhoujy:~# redis -h 192.168.200.25
redis 192.168.200.25:6379> set name zhoujinyi
OK
redis 192.168.200.25:6379> set sex man
OK
redis 192.168.200.25:6379> set age 27
OK
redis 192.168.200.25:6379> save
OK
redis 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.202
redis 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。
  在上一篇文章NoSQL之【Redis】学习(三):Redis持久化 Snapshot和AOF说明 里面已经说了:



利用Replication机制来弥补aof、snapshot性能上的不足,达到了数据可持久化。即Master上Snapshot和AOF都不做,来保证Master的读写性能,而Slave上则同时开启Snapshot
和AOF来进行持久化,保证数据的安全性
  既然Master上持久化不做,只在Slave上做持久化,那Master崩溃数据就会全部丢失,那如何恢复呢?接下来进行测试:
  Master的配置:关闭自动持久化



#save 900 1
#save 300 10
#save 60 10000
appendonly no
  Slave的配置:开启自动持久化



save 900 1
save 300 10
save 60 10000
appendonly yes
appendfilename appendonly.aof
appendfsync everysec
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
  这些配置的意思请看NoSQL之【Redis】学习(二):配置说明 ,重启主从服务器,使配置生效。
  测试:



# 检查配置是否生效
redis 192.168.200.25:6379> keys *
(empty list or set)
redis 192.168.200.25:6379> CONFIG GET save
1) "save"
2) ""
redis 192.168.200.25:6379> CONFIG GET append*
1) "appendonly"
2) "no"
redis 192.168.200.202:6379> CONFIG GET save
1) "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.25
redis 192.168.200.25:6379> keys *
(empty list or set)
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)
redis 192.168.200.202:6379>
root@zhoujy:~# redis -h 192.168.200.25
redis 192.168.200.25:6379> set name zhoujinyi
OK
redis 192.168.200.25:6379> set sex man
OK
redis 192.168.200.25:6379> set age 27
OK
redis 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.202
redis 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
……
# Persistence
rdb_changes_since_last_save:3                #离最后一次保存改变了3个key
aof_enabled:0                                #关闭了aof持久
# Stats
……
# Replication
role:master                                  #该实例为主服务器
connected_slaves:1                           #有一个从服务器连接
slave0:192.168.200.202,6379,online           #从服务器的信息
# CPU
……
# Keyspace
db0:keys=3,expires=0                         #该实例有3个key

#模拟主库异常崩溃
root@zhoujy:~# kill -9 1647
root@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
……
# Persistence
rdb_changes_since_last_save:0                #离最后一次保存改变了0个key
aof_enabled:0                                #关闭了aof持久
# Stats
……
# Replication
role:master
connected_slaves:1
slave0: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 #关闭主Redis
Stopping 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
……
# Replication
role:slave
master_host:192.168.200.25
master_port:6379
master_link_status:down                      # Master已经不可访问了(down)。Slave依然运行良好,并且保留有AOF与RDB文件。
master_last_io_seconds_ago:-1
master_sync_in_progress:0
master_link_down_since_seconds:160
slave_priority:100
slave_read_only:1
connected_slaves:0
# CPU
……
# Keyspace
db0: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      #断开同步
OK
redis 192.168.200.202:6379> INFO                #断开同步成功
# Replication
role:master
connected_slaves:0
2,然后,把RDB文件复制到指定地方:

cp dump.rdb  /var/lib/redis/zhoujy.rdb        #注意相关权限(redis)
root@zhoujy:/var/lib/redis
# /etc/init.d/redis-server start    #启动主Redis
Starting redis-server: redis-server.
查看下日志里面的记录:“* DB loaded from disk: 0.000 seconds”,主已经从RDB文件里面恢复。进入查看下:
redis 192.168.200.25:6379> INFO
# Keyspace
db0:keys=3,expires=0                          #主恢复了3个kye
redis 192.168.200.25:6379> keys *             #数据已恢复
1) "sex"
2) "age"
3) "name

3,最后,重新开启主从:

redis 192.168.200.202:6379> SLAVEOF 192.168.200.25 6379   #从重新把主的内存快照取到,清空本地内存,重放取到的内存快照。
OK
redis 192.168.200.202:6379> INFO
# Replication
role:slave
master_host:192.168.200.25
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_priority:100
slave_read_only:1
connected_slaves:0
  通过此次实验,我们通过在Slave上启的快照,来保证了数据,恢复了Mater。根据上篇持久性介绍的文章,在大数据量的前提下,AOF的增长要比RDB快很多。所以要是对数据的一致性要求不是很高,允许丢失一些数据的话,建议只在从上开启Snapshot来进行持久化,不开启AOF(AOF会阻塞读写?)。同时可以考虑将save中的频率调高一些或者调用一个计划任务来进行定期bgsave的快照存储,来尽可能的保障本地化数据的完整性。样的架构下,如果仅仅是Master挂掉,Slave完整,数据恢复可达到100%;如果Master与Slave同时挂掉的话,数据的恢复也可以达到一个可接受的程度。当然不允许数据丢失的话,就要开启AOF了,不过最好新建的时候就开启,不要中途开启,上篇有说明。
  总结:
         因为在Redis中,持久化和复制的重连都需要一定的开销,极端情况下这个开销会导致数据库的不可用,所以根据自身的情况,建立合适的主从和持久化方案,可以让Redis和系统更稳定的运行。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-88483-1-1.html 上篇帖子: redis 负载均衡 集群配置 下篇帖子: windows下redis的安装配置和php扩展使用phpredis
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表