Redis分布式(一)
Redis 主从复制(replication)
跟 Kafka、RocketMQ、MySQL、Zookeeper—样,Reids 支持集群的架构,集群的节点有主节点和从节点之分。主节点叫master,从节点叫slave。slave会通过复制的技术,自动同步master的数据。
主从复制配置
Redis的主从复制配置非常地简单,只需要在配置文件里面添加一行配置就可以了。
例如一主多从,186是主节点,在每个slave节点的redis.conf配置文件增加一行
replicaof 192.168.0.16 6379
从节点启动之后,就会自动连接到master节点,开始同步数据。
如果master节点变了,比如原来的master宕机,选举出了新的master,这个配置会被重写。
还有一种方式,就是在启动服务时通过参数直接指定master节点:
./redis-sever --slaveof 192.168.0.16 6379
一个正在运行中的节点,可以变成其他节点的从节点吗?
可以,这就是第三种方式,在客户端直接执行slaveof IP port,使该Redis实例成 为从节点
slaveof 192.168.0.16 6379
一个从节点也可以是其他节点的主节点,形成级联复制的关系。
査看集群状态:
redis> info replication
从节点是只读的,不能执行写操作。执行写命令会报错:
(error) READONLY You can't write against a read only replica.
在主节点写入后,slave会自动从master同步数据。
从节点想要单飞,离开集群怎么实现?
把配置文件里面的replica of去掉重启,或者直接断开复制:
redis> slaveof no one
此时从节点会变成自己的主节点,不再复制数据。
主从复制原理
Redis的主从复制分为两类,一种叫全量复制,就是一个节点第一次连接到master节点,需要全部的数据。第二种叫做增量复制,比如之前已经连接到master节点,但是中间网络断开,或者slave节点宕机了,缺了一部分的数据。
连接阶段
1、slave节点启动时(或者执行slaveof命令时),会在自己本地保存master节点 的信息,包括master node的host和ip。
2、slave节点内部有个定时任务replicationCron,每隔1秒钟检查是否有新的 master node 要连接和复制。源码 replication.c 3132 行。
如果发现有master节点,就跟master节点建立连接。如果连接成功,从节点就为连接连理一个专门处理复制工作的文件事件处理器负责后续的复制工作。为了让主节点感知到slave节点的存活,slave节点定时会给主节点发送ping请求。
建立连接以后,就可以同步数据了,这里也分成两个阶段。
数据同步阶段
如果是新加入的slave节点,那就需要全量复制。master通过bgsave命令在本地生成一份RDB快照,将RDB快照文件发给slave节点(如果超时会重连,可以调大 repl-timeout的值)。
问题:如果slave节点自己本来有数据怎么办?
slave节点首先需要清楚自己的旧数据,然后用RDB文件加载数据。
问题:master节点生成RDB期间,接收到的写命令怎么处理?
开始生成RDB文件时,master会把所有新的写命令缓存在内存中。在slave节点保存了 RDB之后,再将新的写命令复制给slave节点。(跟AOF重写rewrite期间接收到的命令的处理思路是一样的)
第一次全量同步完了,主从已经保持一致了,后面就是持续把接收到的命令发送给 slave节点。
命令传播阶段
master node持续把写命令,异步复制给slave node。
总结起来非常地简单,前面用RDB文件,后面把命令发给slave节点,就实现了主从复制。
注意,一般情况下我们不会用Redis做读写分离,因为Redis的吞吐量已经够高了, 做集群分片之后并发的问题更少,所以不需要考虑主从延迟的问题。
跟MySQL—样,主从之间复制延迟是不可避免的,只能通过优化网络来改善。
第二种情况就是增量复制了。
如果从节点有一段时间断开了与主节点的连接,是不是要把原来的数据全部清空, 重新全量复制一遍?这样效率太低了吧?
如果可以增量复制,怎么知道上次复制到哪里?
slave通过master_repl_offset记录的偏移量
redis> info replication
master repl offset:7324556
主从复制的无盘复制(从2.8.18版本开始 支持无盘复制)。
repl-diskless-sync=no
为了降低主节点磁盘开销,Redis支持无盘复制,master生成的RDB文件不保存到磁盘而是直接通过网络发送给从节点。无盘复制适用于主节点所在机器磁盘性能较差但网络宽带较充裕的场景。
主从复制的不足
Redis主从复制解决了数据备份和一部分性能的问题,但是没有解决高可用的问题。
在一主一从或者一主多从的情况下,如果主服务器挂了,对外提供的服务就不可用了,单点问题没有得到解决。跟MySQL—样。
如果每次都是手动把之前的从服务器切换成主服务器,然后再把剩余节点设置为它的从节点,这个比较费时费力,还会造成一定时间的服务不可用。