您的位置:首页 > 数据库 > Redis

Sentinel-Redis高可用方案(一):主从复制

2015-07-10 10:19 483 查看


引言

大概是因为Redis是个人开发的产品,所以Redis的高可用方案是被分成了几块来实现:主从复制、主从切换以及虚拟IP或客户端方案。

从Redis 2.8开始加入对Sentinel机制从而实现了服务器端的主从切换,但目前尚未发现实现虚拟IP或客户端切换方案。


主从复制研究

wget http://download.redis.io/releases/redis-2.8.2.tar.gz
tar xzf redis-2.8.2.tar.gz

mv redis-2.8.2 /opt/

cp redis.conf redis-master.conf

cp redis.conf redis-slave.conf

cd /opt/redis-2.8.2

make

以下是关于 Redis 复制功能的几个重要方面:

1. 一个Master可以有多个Slave;

2. Redis使用异步复制。从2.8开始,Slave会周期性(每秒一次)发起一个Ack确认复制流(replication stream)被处理进度;

3. 不仅主服务器可以有从服务器, 从服务器也可以有自己的从服务器, 多个从服务器之间可以构成一个图状结构;

4. 复制在Master端是非阻塞模式的,这意味着即便是多个Slave执行首次同步时,Master依然可以提供查询服务;

5. 复制在Slave端也是非阻塞模式的:如果你在redis.conf做了设置,Slave在执行首次同步的时候仍可以使用旧数据集提供查询;你也可以配置为当Master与Slave失去联系时,让Slave返回客户端一个错误提示;

6. 当Slave要删掉旧的数据集,并重新加载新版数据时,Slave会阻塞连接请求(一般发生在与Master断开重连后的恢复阶段);

7. 复制功能可以单纯地用于数据冗余(data redundancy),也可以通过让多个从服务器处理只读命令请求来提升扩展性(scalability): 比如说, 繁重的 SORT 命令可以交给附属节点去运行。

8. 可以通过修改Master端的redis.config来避免在Master端执行持久化操作(Save),由Slave端来执行持久化。

分别修改redis-master.conf和redis-slave.conf,

daemonize项,改为yes(缺省为no):daemonize yes

maxmemory项,设最大占用内存为50MB:maxmemory 50mb

而有6种内存过期策略,通过maxmemory-policy修改,一般使用默认值或allkeys-lru:

volatile-lru:只对设置了过期时间的key进行LRU(默认值)

allkeys-lru : 是从所有key里 删除 不经常使用的key

volatile-random:随机删除即将过期key

allkeys-random:随机删除

volatile-ttl : 删除即将过期的

noeviction : 永不过期,返回错误

修改redis-slave.conf中的端口,避免和Master的相同:port 7379

Redis复制工作原理:

1. 如果设置了一个Slave,无论是第一次连接还是重连到Master,它都会发出一个SYNC命令;

2. 当Master收到SYNC命令之后,会做两件事:

a) Master执行BGSAVE,即在后台保存数据到磁盘(rdb快照文件);

b) Master同时将新收到的写入和修改数据集的命令存入缓冲区(非查询类);

3. 当Master在后台把数据保存到快照文件完成之后,Master会把这个快照文件传送给Slave,而Slave则把内存清空后,加载该文件到内存中;

4. 而Master也会把此前收集到缓冲区中的命令,通过Reids命令协议形式转发给Slave,Slave执行这些命令,实现和Master的同步;

5. Master/Slave此后会不断通过异步方式进行命令的同步,达到最终数据的同步一致;

6. 需要注意的是Master和Slave之间一旦发生重连都会引发全量同步操作。但在2.8之后版本,也可能是部分同步操作。

部分复制

2.8开始,当Master和Slave之间的连接断开之后,他们之间可以采用持续复制处理方式代替采用全量同步。

Master端为复制流维护一个内存缓冲区(in-memory backlog),记录最近发送的复制流命令;同时,Master和Slave之间都维护一个复制偏移量(replication offset)和当前Master服务器ID(Master run id)。当网络断开,Slave尝试重连时:

a. 如果MasterID相同(即仍是断网前的Master服务器),并且从断开时到当前时刻的历史命令依然在Master的内存缓冲区中存在,则Master会将缺失的这段时间的所有命令发送给Slave执行,然后复制工作就可以继续执行了;

b. 否则,依然需要全量复制操作;

Redis 2.8 的这个部分重同步特性会用到一个新增的 PSYNC 内部命令, 而 Redis 2.8 以前的旧版本只有 SYNC 命令, 不过, 只要从服务器是 Redis 2.8 或以上的版本, 它就会根据主服务器的版本来决定到底是使用 PSYNC 还是 SYNC :

如果主服务器是 Redis 2.8 或以上版本,那么从服务器使用 PSYNC 命令来进行同步。

如果主服务器是 Redis 2.8 之前的版本,那么从服务器使用 SYNC 命令来进行同步。

配置Slave

只需要将redis-slave.conf中REPLICATION段中的slaveof <masterip> <masterport>行的注释去掉,并修改为:

slaveof 127.0.0.1 6379

即完成该Slave的配置,并指向本地端口为6379的Master端。

masterauth

如果Master端通过requirepass设置了密码,Slave需要对应的通过masterauth <password>设置密码;

slave-serve-stale-data

当Slave和Master断开连接时,Slave是直接返回错误提示还是利用历史数据响应客户端(或是直接返回空数据,当全量复制进行时)。yes是缺省值,即利用历史数据响应。

slave-read-only

缺省模式下,Slave服务器是只读的。

repl-ping-slave-peroid

即心跳检测间隔时间,缺省值为10秒。

repl-timeout 60

复制超时

启动Redis

#redis-server redis-master.conf

#redis-server redis-slave.conf

使用ps查看进程

#ps -ef | grep redis

还可以用netstat查看端口

#netstat -tpln

验证主从复制

#redis-cli set test 1000

#redis-cli get test #只能说明目前Master工作正常,不能说明Slave已经复制数据

根据刚刚查看到的端口号,把端口号是6379的Master进程杀掉

#kill -9 XXXX(PID号)

#redis-cli -p 7379 get test #连接到Slave上,读取test

#redis-cli -p 7379 set test 1000 #会提示Slave只读错误,不能写入
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: