关于Redis的主从复制……

524 阅读5分钟

前言

距离上一篇文章发布又过了一段时间了,哎没办法,最近年底确实是比较忙,但是想起redis还有一部分内容还没写完,还是抽时间出来赶紧把这系列弄完~另外,由于我最近整的大数据的东西,所以,曦轩我暂定下个专题想分享大数据相关的东西~感兴趣的小伙伴们尽请期待噢~搞了大数据之后,才明白一些大咖嘴里说的“大数据和Java不分家”的言论,后端的盆友,有时间的话看看也无妨。至于redis,作为缓存nosql的角色,在大数据中的应用也还是有的,深入了解一下redis的东西,还是对自己的发展很有帮助的哈~

这一篇章主要讲redis分布式方面的东西,主要从主从复制,哨兵机制和方案实现几个方面来阐述。

正文

为什么需要 Redis 集群

为什么需要集群?

性能

Redis 本身的 QPS 已经很高了,但是如果在一些并发量非常高的情况下,性能还是会受到影响。这个时候我们希望有更多的 Redis 服务来完成工作。

扩展

第二个是出于存储的考虑。因为 Redis 所有的数据都放在内存中,如果数据量大,很容易受到硬件的限制。升级硬件收效和成本比太低,所以我们需要有一种横向扩展的方法。

可用性

第三个是可用性和安全的问题。如果只有一个 Redis 服务,一旦服务宕机,那么所有的客户端都无法访问,会对业务造成很大的影响。另一个,如果硬件发生故障,而单机的数据无法恢复的话,带来的影响也是灾难性的。

可用性、数据安全、性能都可以通过搭建多个 Reids 服务实现。其中有一个是主节点(master),可以有多个从节点(slave)。主从之间通过数据同步,存储完全相同的数据。如果主节点发生故障,则把某个从节点改成主节点,访问新的主节点。

Redis 主从复制(replication)

主从复制配置

例如一主多从,203 是主节点,在每个 slave 节点的 redis.conf 配置文件增加一行

slaveof 192.168.8.203 6379

// 在主从切换的时候,这个配置会被重写成:

#Generated by CONFIG REWRITE replicaof 192.168.8.203 6379

或者在启动服务时通过参数指定 master 节点:

./redis-server --slaveof 192.168.8.203 6379

或在客户端直接执行 slaveof xx xx,使该 Redis 实例成为从节点。

启动后,查看集群状态:

redis> info replication

从节点不能写入数据(只读),只能从 master 节点同步数据。get 成功,set 失败。

127.0.0.1:6379> set gupao 666
(error) READONLY You can't write against a read only replica.

主节点写入后,slave 会自动从 master 同步数据。

断开复制:

redis> slaveof no one

此时从节点会变成自己的主节点,不再复制数据。

主从复制原理

连接阶段

  1. slave node 启动时(执行 slaveof 命令),会在自己本地保存 master node 的信息,包括 master node 的 host 和 ip;

  2. slave node 内部有个定时任务 replicationCron(源码 replication.c),每隔 1 秒钟检查是否有新的 master node 要连接和复制,如果发现,就跟 master node 建立 socket 网络连接,如果连接成功,从节点为该 socket 建立一个专门处理复制工作的文件事件处理器,负责后续的复制工作,如接收 RDB 文件、接收命令传播等;

当从节点变成了主节点的一个客户端之后,会给主节点发送 ping 请求。

数据同步阶段

  1. master node 第一次执行全量复制,通过 bgsave 命令在本地生成一份 RDB 快照,将 RDB 快照文件发给 slave node(如果超时会重连,可以调大 repl-timeout 的值)。 slave node 首先清除自己的旧数据,然后用 RDB 文件加载数据。

问题:生成 RDB 期间,master 接收到的命令怎么处理?

开始生成 RDB 文件时,master 会把所有新的写命令缓存在内存中。在 slave node保存了 RDB 之后,再将新的写命令复制给 slave node。

命令传播阶段

  1. master node 持续将写命令,异步复制给 slave node

延迟是不可避免的,只能通过优化网络。

repl-disable-tcp-nodelay no

当设置为 yes 时,TCP 会对包进行合并从而减少带宽,但是发送的频率会降低,从节点数据延迟增加,一致性变差;具体发送频率与 Linux 内核的配置有关,默认配置为40ms。当设置为 no 时,TCP 会立马将主节点的数据发送给从节点,带宽增加但延迟变小。

一般来说,只有当应用对 Redis 数据不一致的容忍度较高,且主从节点之间网络状况不好时,才会设置为 yes;多数情况使用默认值 no。

问题:如果从节点有一段时间断开了与主节点的连接是不是要重新全量复制一遍?

如果可以增量复制,怎么知道上次复制到哪里?

通过 master_repl_offset 记录的偏移量

redis> info replication

主从复制的不足

主从模式解决了数据备份和性能(通过读写分离)的问题,但是还是存在一些不足:

  1. RDB 文件过大的情况下,同步非常耗时。

  2. 在一主一从或者一主多从的情况下,如果主服务器挂了,对外提供的服务就不可用了,单点问题没有得到解决。如果每次都是手动把之前的从服务器切换成主服务器,这个比较费时费力,还会造成一定时间的服务不可用。

By the way

有问题?可以给我留言或私聊 有收获?那就顺手点个赞呗~ 想找工作机会也可以联系我噢~

当然,也可以到我的公众号下「6曦轩」,