Redis高可用技术

16 篇文章 0 订阅

宏观角度回顾一下Redis实现高可用相关的技术。它们包括:持久化、复制、哨兵和集群

  1. 持久化:持久化是最简单的高可用方法(有时甚至不被归为高可用的手段),主要作用是数据备份,即将数据存储在硬盘,保证数据不会因进程退出而丢失。
  2. 复制:复制是高可用Redis的基础,哨兵和集群都是在复制基础上实现高可用的。复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。缺陷:故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机的限制。
  3. 哨兵:在复制的基础上,哨兵实现了自动化的故障恢复。缺陷:写操作无法负载均衡;存储能力受到单机的限制。
  4. 集群:通过集群,Redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。

持久化

RDB方式

对性能的影响相对较小
将redis某一时刻的数据持久化到磁盘中,是一种快照式的持久化方法。所以会存在很多个文件

save //阻塞保存
bgsave //后台不阻塞保存
save m n //当m秒内发生n次变化时,会触发bgsave
主从复制场景下,如果从节点执行全量复制操作,则主节点会执行bgsave命令
执行shutdown命令时,自动执行rdb持久化

AOF方式

实时;文件大、恢复速度慢、对性能影响大
将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令都执行一遍

Redis服务器默认开启RDB,关闭AOF;要开启AOF,需要在配置文件中配置:appendonly yes
因此AOF不需要触发,记录Redis的每条写命令


主从

单机版的Redis属于保证CP(Consistency & Partition-Tolerancy)而牺牲A(Availability)
主从模式是AP

主节点和多个从节点。提供了冗余和故障转移能力,适合一些读多写少的应用场景(主写从读)。

主从复制的开启,完全是在从节点发起的;不需要我们在主节点做任何事情。

从节点开启主从复制,有3种方式:

  1. 配置文件
    在从服务器的配置文件中加入:slaveof <masterip> <masterport>
  2. 启动命令
    redis-server启动命令后加入 --slaveof <masterip> <masterport>
  3. 客户端命令
    Redis服务器启动后,直接通过客户端执行命令:slaveof <masterip> <masterport>,则该Redis实例成为从节点。

通过slaveof no one断开。需要注意的是,从节点断开复制后,不会删除已有的数据,只是不再接受主节点新的数据变化。

全部复制

  • 场景
    用于初次复制或其他无法进行部分复制的情况,将主节点中的所有数据都发送给从节点,是一个非常重型的操作
  • 同步流程
    1. 主节点 bgsave生成当前RDB文件 + 复制缓冲区记录后续命令
    2. RDB文件 发给从节点 >> 从节点清空老数据、载入新RDB文件
    3. 复制缓冲区命令 发给从节点 >> 从节点执行这些写命令

部分复制

Redis2.8开始提供部分复制,
从节点发送psync命令请求同步数据,此时根据主从节点当前状态的不同,选择同步方式是全量复制或部分复制

  • 重要概念

    1. 复制偏移量(offset)
      主节点和从节点分别维护一个:记录节点 传递/接收 的字节数
      判断主从节点的数据库状态是否一致,差多少数据没同步
    2. 复制积压缓冲区
      先进先出(FIFO)队列 默认大小1MB (建议根据 平均中断时间*每秒产生命令 进行调整)
      记录主节点最新执行命令,超过队列大小的会被挤出缓冲区
    3. 服务器运行ID(runid)
      识别每个节点的随机ID(每次启动都不一样)
      从节点会将主节点的runid存起来,断开重连的时候判断是否同步过
  • 场景
    用于网络中断等情况后的复制,只将中断期间主节点执行的写命令发送给从节点,与全量复制相比更加高效。

  • 使用条件
    主节点的runid没变,且 offset之后的数据 在复制积压缓冲区中

哨兵

Redis 2.8版本开始引入。哨兵的核心功能是主节点的自动故障转移

在这里插入图片描述

  • 哨兵节点:
    哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的redis节点,不存储数据。

  • 数据节点:
    主节点和从节点都是数据节点。

哨兵系统部署

哨兵系统中节点分为 数据节点 与 哨兵节点

启动数据节点

哨兵系统中的主从节点,与普通的主从节点配置是一样的

启动哨兵节点

  • 部署建议
    哨兵节点的数量应不止一个,一方面增加哨兵节点的冗余,避免哨兵本身成为高可用的瓶颈;另一方面减少对下线的误判。此外,这些不同的哨兵节点应部署在不同的物理机上。
    哨兵节点的数量是奇数
    哨兵节点的配置应一致,包括硬件、参数、时间
  1. 配置sentinel.conf
//至少需要 N个哨兵节点同意,才能判定主节点故障并进行故障转移。
sentinel monitor 主节点名称 主节点ip 主节点端口 N
//一个哨兵可以监控多个主节点,通过配置多条sentinel monitor即可实现
sentinel monitor ...
sentinel monitor ...
  1. 启动 redis-sentinel
# 启动有两种方式,二者作用是完全相同的
redis-sentinel sentinel.conf

redis-server sentinel.conf --sentinel
  1. 故障转移
    在故障转移阶段,哨兵和主从节点的配置文件都会被改写
  • 对于主从节点,主要是slaveof配置的变化:新的主节点没有了slaveof配置,其从节点则slaveof新的主节点。
  • 对于哨兵节点,除了主从节点信息的变化,纪元(epoch)也会变化,下图中可以看到纪元相关的参数都+1了。

哨兵的原理

  1. 定时任务:
    每个哨兵节点维护了3个定时任务。定时任务的功能分别如下:
    通过向主从节点发送info命令 获取最新的主从结构
    通过发布订阅功能 获取其他哨兵节点的信息
    通过向其他节点发送ping命令进行 心跳检测,判断是否下线。

  2. 主观下线:
    心跳检测的定时任务中,如果其他节点超过一定时间没有回复,哨兵节点就会将其进行主观下线。顾名思义,主观下线的意思是一个哨兵节点“主观地”判断下线;与主观下线相对应的是客观下线。

  3. 客观下线(主节点):
    哨兵节点在对主节点进行主观下线后,会通过sentinel is-master-down-by-addr命令询问其他哨兵节点该主节点的状态;如果判断主节点下线的哨兵数量达到一定数值,则对主节点进行客观下线
    只实现了主节点的故障转移;从节点故障时只会被下线,不会进行故障转移

  4. 选举领导者哨兵节点
    主节点被判断客观下线以后,各个哨兵节点会进行协商,选举出一个领导者哨兵节点,并由该领导者节点对其进行故障转移操作

  5. 故障转移

    1. 在从节点中选择新的主节点:
      slave-priority优先级 > 复制偏移量最大 > runid最小
    2. 更新主从状态:
      通过slaveof no one命令,让选出来的从节点成为主节点;
      通过slaveof命令让其他节点成为其从节点
    3. 将已经下线的主节点设置为新的主节点的从节点
      当重新上线后,它会成为新的主节点的从节点
心跳检测
客观下线
主观下线
选举领导者哨兵节点
故障转移

集群

Redis 3.0开始引入的。提供高可用性、高性能和可扩展性。

通过分片( sharding ) 将数据均匀地分布在多个节点上,
允许在增加或减少节点时进行水平扩展
并提供复制和故障转移。

redis-cluster

  1. redis-cluster 启动节点
  2. 节点握手,形成集群网络
  3. 集群数据分区分配 哈希槽【hash slot】
  4. 【可选】指定主节点副本 cluster replicate
  • 集群节点
    在集群中,没有数据节点与非数据节点之分:所有的节点都存储数据,也都参与集群状态的维护。
    不过节点会开2个端口。
    1. 普通端口
      用于为客户端提供服务,节点数据迁移
    2. 集群端口
      节点之间的通信:增减节点、故障转移等操作

数据分区

将数据自动切分(split)到多个节点的能力。

哈希槽【hash slot】=虚拟节点
  • 概念
    虚拟节点,数据hash不直接放在实际节点,
    变成:数据hash >> 槽 >> 实际节点

  • hash作用:
    扩展写数据能力,让多个节点能承担写数据

  • 槽作用:
    解耦了数据和实际节点之间的关系,增加或删除节点对系统的影响变小

    1. 一致性hash:一个实际节点下线,相邻节点要独自承载它的全部数据
    2. 哈希槽:一个实际节点下线,把它的槽均匀分配给其他节点

计算哈希值使用的算法是CRC16
在这里插入图片描述
图片修改自:https://blog.csdn.net/yejingtao703/article/details/78484151

读数据限制

由于数据分布在不同的节点中,客户端通过某节点访问数据时,数据可能不在该节点中

Dummy客户端
  1. redis-cli -c 请求key
  2. 计算key属于哪个槽:CRC16(key) & 16383
  3. 槽是否在当前节点
    1. 在:执行命令
    2. 不在:查询正确节点,返回错误
  4. 客户端请求正确节点
Smart客户端
  1. Java的JedisCluster 初始化 cluster slots。得到slot->node的缓存
  2. JedisCluster为每个节点创建连接池(即JedisPool)
  3. 根据key->slot->node选择需要连接的节点
    1. 失败:随机重试 + 重新获取 cluster slots

在这里插入图片描述

集群其他限制
批量操作受限

mget、mset操作,只有当操作的key都位于一个槽时,才能进行

keys/flushall等操作

keys/flushall 结果只针对当前节点

事务/Lua脚本:

事务及Lua脚本,所涉及的key必须在同一个节点。

db0数据库

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

复制结构

只支持一层复制结构,不支持嵌套。

Hash Tag:解决部分限制

Hash Tag原理是:让不同的key拥有相同的hash值,从而分配在同一个槽里

具体:当一个key包含 {Hash Tag} 的时候,不对整个key做hash,而仅对 {Hash Tag} 包括的字符串做hash。

高可用

集群中的主从

为了集群节点的高可用,每个集群节点都是由一组主从节点组成
在这里插入图片描述

故障转移

集群中没有独立的哨兵节点。每个Node互相监听

通过定时任务发送PING消息检测其他节点状态;节点下线分为主观下线和客观下线;客观下线后选取从节点进行故障转移。

  1. 心跳检测:每个节点的master 定期的向其他节点 master 发送 ping命令,
  2. 如果没有收到pong 响应,则会认为主观下线,并将这个消息发送给其他的 master。
  3. 其他的 master 在接收到这个消息后就保存起来。当某个节点的 master 收到 半数以上的消息认为这个节点主观下线后,就会判定这个节点客观下线
  4. 故障转移:这个客观节点下线后,其他的 master 节点 就会选举 下线的master中的 slave 一个变成 新的master 继续工作

一致性

不保证数据的强一致性

  • 原因
  1. 主从异步复制延迟
  2. 集群出现网络分裂(network partition), 并且一个客户端与至少包括一个主节点在内的少数(minority)实例被孤立

例如:
一个集群3个节点,各有一个从节点 :A (A1)、 B(B1) 、 C(C1)
A (A1)、 B(B1) 、(C1) 与 C 的网络中断。
C还在接收客户端写请求,C1被转移为主节点。

伸缩:槽均匀迁移

伸缩的核心是槽迁移:修改槽与节点的对应关系,实现槽(即数据)在节点之间的移动

迁移中错误:ASK错误

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值