云数据库Redis版主从热备高可用方案

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 高可用(High Available)是线上生产环境所必不可少的重要条件,阿里云数据库Redis版作为一款成熟稳定的数据库产品,针对Redis的特性也支持高可用,本文将介绍云Redis是如何实现这一方案。 目前云Redis有主从版和集群版两种架构,本次主要针对主从版。

引言

高可用(High Available)是线上生产环境所必不可少的重要条件,阿里云数据库Redis版作为一款成熟稳定的数据库产品,针对Redis的特性也支持高可用,本文将介绍云Redis是如何实现这一方案。

架构

目前云Redis有主从版和集群版两种架构,本次主要针对主从版做HA的解析。

下图为主从版架构:
HA.png
由图可知,云Redis实例有主备两个节点,平时只有Master提供服务,Slave只做热备不提供访问,Slave通过slaveof命令挂载到Master上,不断从Master接收数据,保证Master宕机时云Redis仍可提供服务。

每一个云Redis实例都会分配一个VIP并与DNS绑定,VIP经过SLB后直接访问Master不再有其他中间层,访问Redis的链路为DNS-->VIP-->SLB-->REDIS(MASTER)。

在底层原理上集群版HA与主从版基本相同,只是实现时稍有差异,因为链路上在VIP和后端REDIS之间多了一层proxy的路由转发,所以在做后端rs切换时无需更改VIP指向,而是去更新proxy的路由表。

HA模块

HA作为一个独立的系统模块,远程探测云Redis的健康状况,当发生实例不可用时及时主备切换以保证服务质量。

健康检查

健康检查的逻辑很简单,通过客户端连接Redis并发送PING命令,如果返回PONG则说明Redis健康,其他情况则说明Redis异常,检测逻辑用伪代码来说明:

try:
    client = Redis(ip, port, connection_timeout, socket_timeout)
    //指定要连接Redis的ip:port(这里的ip:port即可以是VIP:VPORT也可以是Master或Slave的物理ip:port,HA会有多维度的探测),并设置超时时间
    client.connect()
    //尝试连接Redis,如果连接失败或超时则会抛出异常
    res = client.ping()
    //向Redis发送ping命令,结果为PONG说明Redis健康,返回OK;结果非PONG或超时则会抛出异常
    if res == PONG:
        return OK
except:
    //处理异常情况,若异常在预先定义的错误内,说明Redis真的异常,返回ERROR,HA会做下一步切换动作
    if e.message in ERRORS:
        return ERROR
    else:
        return OK

需要HA真正做切换的异常情况有以下几种:

/* 指定ip地址的机器不能找到(也就是说从当前机器不存在到指定ip路由),或者是该ip存在,但找不到指定的端口进行监听,这时Redis所在主机可能宕机或是进程挂掉 */
"Connection refused"    
/* 服务器的并发连接数超过了其承载量,服务器会将其中一些连接主动Down掉 */
"Connection reset"
/* 连接超时 */
"connect timed out"
/* 读取数据超时 */
"Read timed out"
/* Redis正在加载数据 */
"LOADING Redis is loading the dataset in memory"
/* 访问的Redis是Slave */
"READONLY You can't write against a read only slave"

健康检查升级方案

Redis工作在单线程模式下,接收到的所有命令都会进入队列串行处理,当遇到一些耗时命令如flushall、keys * 等,很容易造成客户端等待超时。此时如果超时时间设置不准确的话,HA远程探测就容易误判Redis不健康,而且单单一个PING命令也不能完全获得Redis的进程状态。

Redis自带的HA方案Sentinel就是依赖PING来做健康检查,通过配置sentinel down-after-milliseconds mymaster,来决定当PING超时多久没有收到回复就认为Redis宕机,但是这样做有一定风险,比如一个64G的实例flushall清空数据大概为2分钟,如果超时时间设置为60s那么很容易造成误判。

为了解决这个问题,我们对Redis内核进行了改造,增加了一个状态线程来专门为HA提供健康检查的服务。同时也新增了一个状态端口,状态线程监听这个端口,HA探测时也通过这个端口与Redis进行交互,不会对Redis服务主线程造成影响。通过新增的状态线程也可以做很多额外的探测,例如读写性能、磁盘IO情况等。

我们把Redis主线程监听的端口叫做redis_port,状态线程监听的端口叫做status_port新的健康检查逻辑如下:

try:
    client = Redis(ip, status_port, connection_timeout, socket_timeout)
    //这里要连接的端口为状态端口status_port
    client.connect()
    //尝试连接Redis,如果连接失败或超时则会抛出异常
    res = client.health_check()
    //向Redis发送定制的健康检查命令,结果为True说明Redis健康,返回OK;否则抛出异常
    if res == True:
        return OK
except:
    //处理异常情况,若异常在预先定义的错误内,说明Redis真的异常,返回ERROR,HA会做下一步切换动作
    if e.message in ERRORS:
        return ERROR
    else:
        return OK

主备切换前准备工作

当健康检查发现Redis出现不可用情况时就要准备进行主备切换,在主备切换真正执行前需要额外做一些工作:

通过VIP检查Redis健康状态
if VIP不健康:
    检查Slave状态
    if Slave健康:
        再次检查VIP状态
        if VIP健康:
            无需主备切换
        else:
            执行主备切换
    else:
        Slave不健康无法切换
else:
    无需主备切换

在执行切换前要检查Slave状态以确保切换后实例是可服务的,否则即使切换也是无效的,比如两台主机都宕机这种极端情况。

同时对VPC类型的实例做了特殊处理,因为我们是没有办法访问用户自定义网络的VIP的,这时需要把对VIP的健康检查换成对Master的健康检查。

执行主备切换

当Redis出现不可用且满足切换条件时,真正开始执行主备切换动作。同时切换动作也支持主动的任务切换和被动的故障切换,两者主要区别在是否需要Slave等待Master达到同步状态,以下对主备切换做详细说明:

1. 额外再次检查一次Master状态
if Master健康:
    if 故障切换:
        无需切换,返回成功
    else:
        a. 设置Master为readONLY只读状态
        b. 通过info replication命令检查主备同步状态,也即master_repl_offset是否等于Slave的offset
        if 若超时仍未达到一致状态:
            重置Master为readwrite可读写状态,并返回异常
else:
    日志记录此时Master无法连接
2. 切换VIP指向Slave
if 切换失败:
    记录日志并返回异常
3. 更新主备元信息
4. 向Slave发送slaveof no one命令,使其升级为新的Master
5. 尝试向原Master发送slaveof命令,使其降级为新的Slave
    此时原Master可能已经宕机,故不做失败处理,仅记录日志

通过以上方案,云数据库Redis版SLA可以达到99.99%,仅在主从都发生宕机的极端情况无法服务。

切换场景

宕机或是进程异常退出是最为严重的情况,此时HA远程探测到redis无法连接会立即切换,实际测试整个过程可以实现秒级切换。

在主备切换后原来的Master变成了Slave,为了保障云Redis依旧高可用,会有另外的组件来探测Slave的可用性,当备库发生宕机时触发备库重搭功能,时刻保证主从双节点热备。

与Redis-Sentinel对比

Redis2.8版本自带Redis-Sentinel的高可用解决方案,通过一个或多个Sentinel实例组成的Sentinel系统来监测Master和Slave,具体方案有很多资料可以查阅不再赘述。
我们在生产环境中并没有采用自带的Sentinel,主要是出于以下几点考虑:

1. 虽然Sentinel本身也是一个Redis进程,但是运行在特殊模式下,实际维护Sentinel就需要额外配置一个角色,增加了系统的复杂度。
2. Sentinel自身的高可用问题,如果是单点Sentinel其本身也具有故障无法转移的风险,那么就要搭建Sentinel集群,这无形中也增加了管理成本。
3. Sentinel本身是有状态的,需要在启动时加载配置文件来获取Master信息,如果搭建分布式的Sentinel集群,动态增删改也会带来一致性问题,这对云上弹性资源并不适用,无法应对实例的创建、删除、变配、迁移等动作。
4. Sentinel的健康检查并不够灵活,上一节已经讲过单纯通过PING来检查无法应对flushall、keys * 等耗时命令,我们的健康检查升级方案会更好的应对云上复杂环境。

由于上述问题Sentinel不能作为一个统一的HA系统来管理所有云Redis资源,而为每个云Redis单独搭建一套Sentinel系统又会造成资源浪费和管理复杂度,基于此我们开发了这一套适用于云Redis的HA系统。

结束

本文介绍了云数据Redis版HA方案,通过主从双机热备来保证服务高可用,健康检查出现异常时及时进行主备切换,有效保障业务运行。

结尾顺便打个硬广,即日起购买阿里云数据库Redis版(首台)3年5折、1年6折、按月7折啦,赶快点击购买吧:https://m.aliyun.com/markets/aliyun/act/redissaleoff?spm=5176.8112568.483450.6.o85c4v

阿里云数据库Redis团队诚邀加入:
https://job.alibaba.com/zhaopin/position_detail.htm?spm=0.0.0.0.l7roxQ&positionId=26437

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
18天前
|
负载均衡 监控 NoSQL
Redis的集群方案有哪些?
Redis集群包括主从复制(基础,手动故障恢复)、哨兵模式(自动高可用)和Redis Cluster(官方分布式解决方案,自动分片和容错)。此外,还有如Codis、Redisson和Twemproxy等第三方工具用于代理和负载均衡。选择方案需考虑应用场景、数据规模和并发需求。
17 2
|
3月前
|
监控 NoSQL Linux
【分布式】Redis的持久化方案解析
【1月更文挑战第25天】【分布式】Redis的持久化方案解析
|
3月前
|
NoSQL 关系型数据库 MySQL
Redis高可用之主从复制架构(第一部分)
Redis高可用之主从复制架构(第一部分)
|
3月前
|
存储 监控 NoSQL
Redis 高可用之主从模式
上一节RDB和AOF持久化机制提到了 Redis 的持久性,也就是在服务器实例宕机或故障时,拥有再恢复的能力。但是在这个服务器实例宕机恢复期间,是无法接受新的数据请求。对于整体服务而言这是无法容忍的,因此我们可以使用多个服务器实例,在一个实例宕机中断时,另外的服务器实例可以继续对外提供服务,从而不中断业务。Redis 是如何做的呢?Redis 做法是**增加冗余副本**,**将一份数据同时保存在多个实例**上。那么如何保存各个实例之间的数据一致性呢?
45 0
Redis 高可用之主从模式
|
3月前
|
机器学习/深度学习 NoSQL Redis
Redis高可用之集群架构(第三部分)
Redis高可用之集群架构(第三部分)
|
3月前
|
消息中间件 NoSQL Redis
Redis高可用之哨兵模式(第二部分)
Redis高可用之哨兵模式(第二部分)
|
21天前
|
缓存 运维 NoSQL
【Redis故障排查】「连接失败问题排查和解决」带你总体分析和整理Redis的问题故障实战开发指南及方案
【Redis故障排查】「连接失败问题排查和解决」带你总体分析和整理Redis的问题故障实战开发指南及方案
60 0
|
3月前
|
存储 监控 NoSQL
|
2月前
|
存储 NoSQL Java
面试官:Redis如何保证高可用?
面试官:Redis如何保证高可用?
76 2
面试官:Redis如何保证高可用?
|
3月前
|
监控 NoSQL 程序员
Redis 高可用篇:你管这叫 Sentinel 哨兵集群原理
Redis 高可用篇:你管这叫 Sentinel 哨兵集群原理
77 5