Redis之主从复制、哨兵、集群

Redis之主从复制、哨兵、集群

Redis在主从模式下会有许多问题需要考虑,这里写了一些关于redis在多服务器下的一些问题分析和总结。学习的文章源地址:https://www.cnblogs.com/kismetv/p/9236731.html#t61

Redis的主从复制

在读了关于redis主从复制的文章后,总结一下主从复制的作用、过程以及可能存在的问题。

  • 作用
    1、实现故障恢复:主从模式可以在主节点挂掉之后,由从节点提高服务,实现快速的故障恢复。
    2、实现负载均衡:由主节点负责写操作,而其他从节点负责读取操作,分担服务器负载。
    3、高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础

  • 如何建立
    在配置文件里面进行配置,注意一个主库能有多个从库,而一个从库只能对应一个主库。

  • 主从复制的三个阶段
    连接建立阶段(即准备阶段)、数据同步阶段、命令传播阶段

  • 复制模式
    全量复制:
    1、第一次建立复制,
    2、主库宕机,导致主服务器运行ID改变
    3、网络中断并且缓冲区无法保存完全中断期间的数据
    部分复制:
    1、网络中断(缓冲区能够保存中断期间的所有数据)
    2、网络中断后重连主服务器运行ID与原来一致

判断执行哪种复制?Redis之主从复制、哨兵、集群_第1张图片

  • 数据同步过程(psync命令)
    过程:从库想主库发送psync命令请求数据,主库收到后在后台执行快照保存生成RDB文件放进缓冲区中,然后发给从库执行该文件实现同步。
    机制:心跳机制、复制偏移量

思考问题:

  • 主从复制是如何保证主从服务器处于连接状态并且保证命令不丢失?
    1、心跳机制,主库会每隔一段时间(默认10s)发送一个PING给从库,从库会返回给主库一个REPLCONF ACK来确定处于连接状态。
    2、从库会发送一个复制偏移量(offset)给主库,主库会对比是否一致,不一致会补发缺失的数据。
    3、通过配置文件可以配置当主节点处于不安全状态(从库连接少于3个、延时超过10s),主库会拒绝写操作。
# 未达到下面两个条件时,写操作就不会被执行
# 最少包含的从服务器
# min-slaves-to-write 3
# 延迟值
# min-slaves-max-lag 10

主服务器信息中可以看到所属的从服务器的连接信息,state表示从服务器状态,offset表示复制偏移量,lag表示延迟值(几秒之前有过心跳检测机制)Redis之主从复制、哨兵、集群_第2张图片

  • 一主多从情况下怎么减少主库压力?(蘑菇街)
    可以使用拓扑结构,使一些从节点作为其他从节点的主节点,由他们来负责其他节点的主从复制操作,减少主库的压力。(这样会造成延时增他,数据一致性变差)

  • 如何解决数据一致性问题? https://github.com/huangz1990/redis/issues/23
    1、优化主从库之间的网络状况,如放置在同一个机房中
    2、通知应用不对延时大的从节点进行读取操作

  • 数据过期问题?
    在Redis3.2版本中增加对数据过期的判断,解决了这个问题

Redis哨兵

redis的哨兵机制是来实现自动化的故障恢复,不过只能实现主节点的故障切换恢复,无法对从节点实现故障恢复。

  • 介绍
    1、一种特殊的Redis节点(不存储数据),监控主从节点状态(一个或多个)
    2、哨兵节点启动和故障转移,各个节点的配置文件会被重写

  • 哨兵节点的三个定时任务
    1、向主从节点发送info获取最新主从结构
    2、发布订阅功能获取其他哨兵消息(判断客观下线)
    3、PING命令进行心跳检测,判断是否下线(主观下线)

  • 原理过程
    主节点会被多个哨兵节点监控,当主节点发生故障宕机挂掉了,哨兵节点通过心跳检测判断其出现故障下线了(主观下线),如果判断下线的哨兵节点超过一定数量,则判断为客观下线,通过Raft算法(先到先得)来协商出一个领导哨兵节点进行故障转移操作,选出一个从节点升级为主节点,原来的主节点会变成新主节点的从节点。

哨兵总结

在主从复制的基础上,哨兵引入了主节点的自动故障转移,进一步提高了Redis的高可用性;但是哨兵的缺陷同样很明显:哨兵无法对从节点进行自动故障转移,在读写分离场景下,从节点故障会导致读服务不可用,需要我们对从节点做额外的监控、切换操作。
此外,哨兵仍然没有解决写操作无法负载均衡、及存储能力受到单机限制的问题;这些问题的解决需要使用集群,

思考问题:

  • 怎么选择从节点的?
    1、先过滤掉那些不健康的从节点
    2、根据优先级选择(slave-priority值越小越好,设为0则没有机会)
    3、无法区分优先级,根据复制偏移量大的来(offset)
    4、无法区分复制偏移量,则选择运行ID最小的
  • 配置哨兵节点需要注意的地方?
    1、配多几个哨兵节点,并且部署在不同物理机上,防止误判主节点故障
    2、配置个数最好为奇数,容易‘决策’

Redis集群(cluster)

  • 集群的作用

集群的作用,可以归纳为两点:

1、数据分区:数据分区(或称数据分片)是集群最核心的功能。

集群将数据分散到多个节点,一方面突破了Redis单机内存大小的限制,存储容量大大增加;另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力。

Redis单机内存大小受限问题,在介绍持久化和主从复制时都有提及;例如,如果单机内存太大,bgsave和bgrewriteaof的fork操作可能导致主进程阻塞,主从环境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出……。

2、高可用:集群支持主从复制和主节点的自动故障转移(与哨兵类似);当任一节点发生故障时,集群仍然可以对外提供服务。

  • 集群整个搭建过程
    启动节点-》节点握手-》分配槽-》建立主从关系

集群的搭建可以分为四步:(1)启动节点:将节点以集群模式启动,此时节点是独立的,并没有建立联系;(2)节点握手:让独立的节点连成一个网络;(3)分配槽:将16384个槽分配给主节点;(4)指定主从关系:为从节点指定主节点。
实际上,前三步完成后集群便可以对外提供服务;但指定从节点后,集群才能够提供真正高可用的服务。

  • 集群之间有主节点挂了怎么处理?
    集权内部有故障转移功能,大体思路和哨兵差不多,不过细节不同,并不是建立哨兵节点来监控,而是通过其他主节点进行通信来判断,所有节点都携带有数据。、

在 哨兵 一文中,介绍了哨兵实现故障发现和故障转移的原理。虽然细节上有很大不同,但集群的实现与哨兵思路类似:通过定时任务发送PING消息检测其他节点状态;节点下线分为主观下线和客观下线;客观下线后选取从节点进行故障转移。
与哨兵一样,集群只实现了主节点的故障转移;从节点故障时只会被下线,不会进行故障转移。因此,使用集群时,应谨慎使用读写分离技术,因为从节点故障会导致读服务不可用,可用性变差。
这里不再详细介绍故障转移的细节,只对重要事项进行说明:
节点数量:在故障转移阶段,需要由主节点投票选出哪个从节点成为新的主节点;从节点选举胜出需要的票数为N/2+1;其中N为主节点数量(包括故障主节点),但故障主节点实际上不能投票。因此为了能够在故障发生时顺利选出从节点,集群中至少需要3个主节点(且部署在不同的物理机上)。
故障转移时间:从主节点故障发生到完成转移,所需要的时间主要消耗在主观下线识别、主观下线传播、选举延迟等几个环节;具体时间与参数cluster-node-timeout有关,一般来说:
故障转移时间(毫秒) ≤ 1.5 * cluster-node-timeout + 1000
cluster-node-timeout的默认值为15000ms(15s),因此故障转移时间会在20s量级。

  • 集群间如何实现通信的?

集群中的每个节点都有两个端口:1、普通端口,2、集群端口
1、普通端口:即我们在前面指定的端口(7000等)。普通端口主要用于为客户端提供服务(与单机节点类似);但在节点间数据迁移时也会使用。
2、集群端口:端口号是普通端口+10000(10000是固定值,无法改变),如7000节点的集群端口为17000。集群端口只用于节点之间的通信,如搭建集群、增减节点、故障转移等操作时节点间的通信;不要使用客户端连接集群接口。为了保证集群可以正常工作,在配置防火墙时,要同时开启普通端口和集群端口。

  • 访问的数据不在当前节点怎么办?

当访问数据不在当前节点,会通过计算键对应的哈希值进行与’总槽个数-1‘(16383)进行位与操作获得对应下标找到对应的槽位置并找到对应的节点。
集群也是一个无中心配置。

  • 集群最少个数是多少,为什么?

集群中最少要6个节点,即3个主节点3个从节点。因为在故障转移阶段,需要由主节点投票选出哪个从节点成为新的主节点;从节点选举胜出需要的票数为N/2+1;其中N为主节点数量(包括故障主节点),但故障主节点实际上不能投票。因此为了能够在故障发生时顺利选出从节点,集群中至少需要3个主节点(且部署在不同的物理机上)。

  • 集群的缺陷?

(1)key批量操作受限:例如mget、mset操作,只有当操作的key都位于一个槽时,才能进行。针对该问题,一种思路是在客户端记录槽与key的信息,每次针对特定槽执行mget/mset;另外一种思路是使用Hash
Tag,将在下一小节介绍。

(2)keys/flushall等操作:keys/flushall等操作可以在任一节点执行,但是结果只针对当前节点,例如keys操作只返回当前节点的所有键。针对该问题,可以在客户端使用cluster
nodes获取所有节点信息,并对其中的所有主节点执行keys/flushall等操作。

(3)事务/Lua脚本:集群支持事务及Lua脚本,但前提条件是所涉及的key必须在同一个节点。Hash Tag可以解决该问题。

(4)数据库:单机Redis节点可以支持16个数据库,集群模式下只支持一个,即db0。

(5)复制结构:只支持一层复制结构,不支持嵌套。

  • 集群中某一段主从节点全挂了如何解决?

参数:cluster-require-full-coverage

你可能感兴趣的:(redis,优化,分布式系统)