什么是主从复制(Master/Slave)?
我们的数据一般是存储在数据库中,为了保证数据的高可用,我们一般使用多台数据库服务器做集群。选则其中的一台作为主服务器(Master),其余的作为从服务器(Slave)。Master 上的数据更新后根据配置文件配置的策略,自动同步到 Slave 上,这就是主从复制。
主从复制有什么作用?
- 保证了数据的高可用。因为数据在多台服务器上存储了多份,即使一台机器宕掉了,其余的机器还可以顶上。
- 实现了读写分离。什么叫读写分离?写数据在 Master 上,读数据是在 Slave 上,这就叫读写分离。它缓解了以往 Master 既要处理读数据又要处理写数据的压力,Master 上负责写,Slave 上负责读,大大提升了数据库服务器的性能。
- 容灾恢复。当主机宕掉了之后,就没有办法向数据库中写数据了,怎么办?其余的 Salve 根据配置的策略,选出一台晋升为 Master,其余的 Slave 成为新 Master 的从机,当原来宕掉的 Master 恢复后,自动成为 Slave,实现了容灾
复制命令
- info replication 查看当前主机是master还是slave(默认为master)。
- slaveof 主机的ip 端口号 将当前机器设置为从机。
Redis 实现主从复制的原理是什么?
知其然还要知其所以然。
一、master 复制数据给 slave 的原理如下:
- slave 启动成功之后连接到 master 后会发送一个 sync 命令。
- master 接收到这个同步命令之后启动后台的存盘进程,即将内存的数据持久化到 rdb 或 aof。
- 持久化完毕之后,master 将整个数据文件传送给 slave。
二、slave 接收 master 复制过来的数据方式有两种:
全量复制:
- slave 刚与 master 建立连接的时候,会将接收到的 master 发来的整个数据库文件存盘并加载到内存。
增量复制:
- slave 已经与 master 建立好连接关系的时候,master 会将收集到的修改数据的命令传送给 slave,slave 执行这些命令,完成同步。而不是再一次重新加载整个数据文件到内存。
当然,如果 slave 与 master 断开连接,再次重连的时候还是要加载整个数据文件的,需要重新slaveof。
Redis 的主从复制的缺点
- 当 master 需要同步发送到 slave 上的数据量非常大的时候,会存在一定的时延。
-
当系统很繁忙或者 slave 机器数量非常多的时候也会使这个问题更加严重。
几种模式
一、一主二仆
一个 Master 两个 slave。
这种模式会遇到一些问题,再次记录一下:
- slave 在连接 master 之前,master 就已经添加了一些 key,那么 slave 连接进来的时候之前的 key 是否也会复制?
答:全部都会复制,即全量复制。
- 是否可以向 slave 里面写数据?是否可以 set key?
答:不可以,slave 只可以 read,master 既可以 read 又可以 write。
- 主机 shutdown 后从机情况如何?从机是上位(变 master)还是原地待命?
答:原地待命,依旧是 slave,等待 master 上位。
- 主机又回来了后,主机新增记录,从机能否顺利复制?
答:必须能。
- 其中一台 slave 宕机后,再次上线还能跟的上大部队吗?
答:不能,必须再次使用 slaveof host port 命令指定主机才可以继续复制数据。
二、薪火相传
- master 和 slave 之间以链表的形式连接起来,上一个 slave 是下一个 slave 的 master。
- 这样 master 就多了,可以有效的缓解主 master 的写压力。
- 如果其中的一个节点宕掉了,后续节点将无法得到之前节点的数据。
三、反客为主
- 使用 slaveof no one 命令,将原本的 slave 转成 master,停止与其他数据库的同步。
四、哨兵模式
它是反客为主的自动版,能够在后台自动监控主机是否故障,如果主机故障了,其余的从机会自动进行投票选举,得票数最多的从机将转换为 master。
Redis的哨兵(sentinel) 系统用于管理多个 Redis 服务器,该系统执行以下三个任务:
- 监控(Monitoring): 哨兵(sentinel) 会不断地检查你的Master和Slave是否运作正常。
- 提醒(Notification):当被监控的某个 Redis出现问题时, 哨兵(sentinel) 可以通过 API 向管理员或者其他应用程序发送通知。
- 自动故障迁移(Automatic failover):当一个Master不能正常工作时,哨兵(sentinel) 会开始一次自动故障迁移操作,它会将失效Master的其中一个Slave升级为新的Master, 并让失效Master的其他Slave改为复制新的Master; 当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用Master代替失效Master。
如何实现哨兵模式
- 开启三个 redis 服务:6379,6380,6381。
- 先让 6379 成为 master,其余两个服务成为它的 slave。
- 在自定义的 /myconf 目录下新建 sentinel.conf 文件,必须是这个名字。
- 在里面填写内容:sentinel monitor 被监控的数据库名字(随意) 192.168.198.130 6379 1 。上面最后一个数字 1,表示 master 宕掉后,slave 投票看让谁接替成为主机,得票数最多的成为主机。
- 启动哨兵:redis-sentinel /myconf/sentinel.conf,这个 /myconf 目录根据自己的实际情况进行配置。
- 这样当我们把 master shutdown 之后,开启的哨兵服务会自动从剩余的两个 slave 投票选出一个当 master,而当原来的 master 上线之后会成为 从机
集群
redis cluster在设计的时候,就考虑到了去中心化,去中间件,也就是说,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。
Redis 集群没有并使用传统的一致性哈希来分配数据,而是采用另外一种叫做哈希槽 (hash slot)
的方式来分配的。redis cluster 默认分配了 16384 个slot,当我们set一个key 时,会用CRC16
算法来取模得到所属的slot
,然后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384。
Redis 集群会把数据存在一个 master 节点,然后在这个 master 和其对应的salve 之间进行数据同步。当读取数据时,也根据一致性哈希算法到对应的 master 节点获取数据。只有当一个master 挂掉之后,才会启动一个对应的 salve 节点,充当 master 。
需要注意的是:必须要3个或以上
的主节点,否则在创建集群时会失败,并且当存活的主节点数小于总节点数的一半时,整个集群就无法提供服务了。
从这种redis cluster的架构图中可以很容易的看出首先将数据根据hash规则分配到6个slot中(这里只是举例子分成了6个槽),然后根据CRC算法和取模算法将6个slot分别存储到3个不同的Master节点中,每个master节点又配套部署了一个slave节点,当一个master出现问题后,slave节点可以顶上。这种cluster的方案对比第一种简单的主从方案的优点在于提高了读写的并发,分散了IO,在保障高可用的前提下提高了性能。