Redis复制
为了避免单点故障,我们希望将数据库的数据实时复制到其他服务器上。那么,即使一台服务器出了问题,其他服务器仍然可以提供服务。
主数据库(master),从数据库(slave)
- master是读写的,发生写行为就传给slave。slave是只读的,只接收来自主库同步的数据(可以配置成可读写)。
- 主库可以有多个从库,从库只能有一个主库,从库下面还能有从库。
- 从库可以激活成主库。
- 一个软件可以起多个实例,同时起主库与从库也是可以的。
实验:
下面我们模拟一个主机上一套软件起主库,从库。
1.启动从库实例。
使用自定义port覆盖参数文件中的port,并且设置认证密码参数,masterauth参数的作用是使实例如果成为从库时,会用这个密码认证来连到主库获取数据。
nohup redis-server /home/ldh/redis/redis-2.8.3/redis.conf --port 6390 --masterauth pass1234 &
当然,
masterauth
也可以在redis.conf配置文件中设置
2.登陆从库实例。
从库使用6390的端口,主库使用6389。
redis-cli -p 6390 -a pass1234
3.设置自己为从库,并指定从什么IP与端口接收数据。
127.0.0.1:6390> slaveof 127.0.0.1 6389
OK
此时就配置成功了,主库不用做任何事情。Redis的美在于简洁。slaveof参数也可以在配置文件中先设定。
4.验证
[ldh@hauser redis-2.8.3]$ redis-cli -p 6389 -a pass1234
127.0.0.1:6389> set fwy ppp
OK
127.0.0.1:6389> exit
[ldh@hauser redis-2.8.3]$ redis-cli -p 6390 -a pass1234
127.0.0.1:6390> get fwy
"ppp"
127.0.0.1:6390>
从库不能写了
127.0.0.1:6390> set fwy 1
(error) READONLY You can't write against a read only slave.
slave-read-only 设置为no就可以使从库可写,适合保存一些短暂数据,但是主库一旦同步了相应的数据就会覆盖掉从库的。
复制原理:
从库发出slaveof 127.0.0.1 6389命令的一刻,在从库实例启动的一刻(slaveof
参数预先已配置好)
- 利用tcp/ip协议与127.0.0.1 6389连接;
- 告知自己的端口号;
- 发送sync命令。此时主库会做一次RDB持久化,并将保存期间的用户命令缓存起来,快照完成后,会将rdb文件与缓存命令,以及后续按时间生成的写都发给从库;
- 从库接收到后,将内容写到硬盘的临时文件上。写入完成后从库会用该临时文件替换RDB快照文件,再载入内存,并且接收缓存命令与后续的写。
注意:
1.每次断开后,上述步骤都得从走一次。同步过程中,从库不会堵塞,而是可以处理客户端的命令,从库会用同步前的数据对客户进行响应。可以配置slave-serve-stale-data参数为No来使从库在同步完成前,对所有命令(除了INFO与SLAVEOF)都回复“sync with master in progress"。
2.复制的过程中,快照无论在主库还是从库都起到很大作用。只要执行复制就会进行快照,即使我们关闭了主库的RDB方式的持久化(通过删除所有save参数),更进一步,无论是否启用了RDB方式的持久化,REDIS在启动的时候都会尝试读取dir和dbfilename两个参数指定的RDB文件来恢复数据库。
redis复制应用场景
读写分离:
常见的场景中,读的频率大于写,当主机无法应付大量的读请求时(尤其是耗资源的如sort排序命令),可以建立多个从库,主库写,多个从库读的方式。
从数据库的持久化
从库配置了dir与dbfilename,save参数等,就会进行RDB持久化。实际上,我们可以将主库的持久化禁用。
此时从库崩溃后重启同步后会将主库的数据传过来,无需担心从库有数据丢失。而当主数据库崩溃时,需要在从数据库中使用slaveof no one命令将从库激活成主库继续提供服务,并在原来的主库启动后使用slaveof命令将其设为从库,又可以将数据同步回去。只有在主从库同时失效时,才会有那么点数据损失。