首页 > 代码库 > try redis (五) -- master -slave 主从复制
try redis (五) -- master -slave 主从复制
参考官网原文:http://redis.io/topics/replication
参考文章 :http://in.sdo.com/?p=1187
注意事项
Redis 的复制说白了就是通过配置 将slave 当做 masters 的复制。但是有有几个需要注意点:
1、Redis使用的是一部复制。从Redis 2.8开始,slaves 将定期确认从复制流中处理的数量
2、一个master 可以有多个slavers
3、slaves可以接受其他slaves 的连接。
4、Redis的复制是不会阻塞master 的,也就是所谓的 non-blocking.这就意味着当一个或者多个slaves 在处理最初的同步时,master可以继续他的查询操作等。
5、为了有多个只读slaves,可以用俩做一些伸缩性的复制。
6、复制操作有可能也可以避免Redis将所有的数据集写入disk的损失。
master持久化变与复制的安全性
当 Redis 复制使用的时候,它是强烈建议master的持久化是开启的,当没法开启持久化比如需要延迟,Redis 需要配置成 禁止自动重启
为了更好的 理解为什么master 在自动重启的 情况下,关闭持久化配置是危险的。可能造成数据从master 和所有slaves 中擦除,我们看一个例子
1、我们启动nodeA 作为master,同时设置A 为持久化 turned down 。node B、C 从A 中复制数据
2、如果A 突然挂了,然后可以重启,但是由于没有开启持久化。重启后数据集为空
3、这个似乎 B 和 C将从 A 中复制空的数据集,这样原来的一些老的数据就被擦除了。
当 redis 系统为了提高可用率,会将master的持久化给关闭。但是任何时候,数据安全都是最重要的,复制功能在没有配置持久化,同时又自动重启的机器中是不可取的。
Reids 复制时怎么工作的
当启动一个slave ,连接后他会发送一个SYNC命令,在它第一次连接或者重新连接master的时候,这个都是正常的。
master 开始后台进行保存操作,同时开始开始缓存所有收到的改变数据集的命令。当后台保存成功,master将 保存在硬盘上的 数据集文件(dump.rdb) 读入到内存中 ,发送给slave。然后master将发送所有缓存命令,这好比是一个命令流,是redis协议本身实现的
Slaves 可以自动冲洗连接。当 master <-> salve 连接因为某些原因中断的时候。当master收到多个并发 slave 同步请求的时候,会有一个单独的线程专门来保存他们。
同时在网上找打一个 比较好的一个状态流程的解释
- 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.conf 关于 配置
port 6379
指定Redis监听端口,默认端口为6379
################################# REPLICATION ###################################
maseter-slave 复制 需要注意几个点
1、redis 复制时一部实现的,但是你可以配置 master 在不能连接到一个给定数量的slaves 的时候,禁止写入
2、redis slaves 可以局部的再同步数据到master 如果master突然断掉。然后启动。
3、复制时自动进行的。不需要用户调用。如果slavers 与master 无法连接。slaves 会尝试连接master.同时再同步slaves上的数据到master上
######################################################################################
slaveof <masterId> <masterPort>
如果配置了slaveof 属性,意味着当前节点是 slave。同时确定了master的ip 和 端口
slave-serve-stale-data yes
当 slaves 和 master 失去联系或者 复制数据工作仍然在进行。这个适合slave 会有两种选择
当配置 yes(默认的) 意味着slave 会反馈 客户端的请求
当配置 no 客户端会反馈一个error "SYNC with master in progress" ,如果master 无法连接上,则会报"MASTERDOWN Link with MASTER is down and slave-serve-stale-data is set to ‘no‘."
slave-read-only yes
用官方的话说,就是保护slave ,不让它暴露在不受信任的客户端上。一般用来当做保护层,尤其在果断的client的时候。
当配置yes(默认)的时候,意味着客户端没法给slave 节点写入数据,一写就会报错"READONLY You can‘t write against a read only slave."
当配置成 no 的时候,任何客户端都可以写入
masterauth
当master服务设置了密码保护时,slave服务连接master的密码
# requirepass foobared
设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH 命令提供密码,默认关闭
开始测试
感觉基本的属性就这些,下面感觉自己要开始做实验了。由于手头就两台机器,就准备搭建个三个节点的测试环境
masdter: A(10.13.145.36:6379)
slaves: B(10.13.145.35:7000)、C (10.13.145.36:7001) ---特别说明我的slaves放在一台机器上,起多个server服务模拟
A(10.13.145.36)就不用配置,全部使用默认配置即可
B的集群配置文件(redis_b.conf)如下:
...
daemonize yes #后台启动
port 7000 #服务端口
slaveof 10.13.145.36 6379 #配置master A
slave-serve-stale-data yes
slave-read-only yes
...
启动 redis-server实例 ./redis-server redis_b.conf
同理C 的配置如下:
C的集群配置文件(redis_c.conf)如下: --C的配置需要注意,我把slave-read-only 设置成 no 了
...
daemonize yes #后台启动
port 7001 #服务端口
slaveof 10.13.145.36 6379 #配置master A
slave-serve-stale-data yes
slave-read-only no
...
启动 redis-server实例 ./redis-server redis_c.conf
好。到此为止,所有的准备工作都 OK了。剩下的就是我们来测试 和验证下 Redis 的复制和替换功能。
有几种场景,我们都可以假设下,并且开始做实验。
一、A(master) 挂了。从B 、C 上是否可以取到数据
1在A(master) 中写入 key1 的数据
10.13.145.36:6379> SET key1 data1 OK 10.13.145.36:6379> get key1 "data1"2、这个时候,终止A 服务,然后开始从 B、C 上取值
从B上取值:
10.13.145.35:7000> get key1 "data1"
从C 上取值:
10.13.145.36:7000> get key1 "data1"3、得出结论:master 挂了。还是可以从 B、C 上取到值
二、A(master) 挂了。从C写入数据data。看是否会复制到B。同时 A(master)又起来了。是否A上是否能查到data. 这时候 B上能否查到data
1、 停掉A,
2、在C中写入数据
10.13.145.35:7000> SET key2 data2 OK 10.13.145.35:7000> get key2 "data1"3、启动A(master) 服务,从C 中读入数据 key2
10.13.145.35:7000> get key2 (nil)
三、A (master)一直ok ,然后B 挂了。给A 写入 data。然后B起来,看B上是否有data.
这个就不做测试了。slave每次启动发送 SYNC 命令,肯定会有数据
总结
- Redis的复制功能没有增量复制,每次重连都会把主库整个内存快照发给从库,所以需要避免向在线服务的压力较大的主库上增加从库。
- 启动时,resdis slaves 每秒都会ping master .确认复制流的进度.而master 每次都会记录每个slaver 最后 ping 的时间
- 自带的复制功能不好用。尤其是针对大的项目。现在开始去研究redis-cluster了。貌似3.0才支持。但是不是稳定版本。
try redis (五) -- master -slave 主从复制