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

本文涉及的产品
RDS PostgreSQL Serverless,0.5-4RCU 50GB 3个月
推荐场景:
对影评进行热评分析
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: 高可用(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
目录
相关文章
|
6月前
|
中间件 关系型数据库 Java
MySQL数据库分库分表方案
MySQL数据库分库分表方案
286 0
MySQL数据库分库分表方案
|
2月前
|
消息中间件 canal 缓存
项目实战:一步步实现高效缓存与数据库的数据一致性方案
Hello,大家好!我是热爱分享技术的小米。今天探讨在个人项目中如何保证数据一致性,尤其是在缓存与数据库同步时面临的挑战。文中介绍了常见的CacheAside模式,以及结合消息队列和请求串行化的方法,确保数据一致性。通过不同方案的分析,希望能给大家带来启发。如果你对这些技术感兴趣,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!
152 6
项目实战:一步步实现高效缓存与数据库的数据一致性方案
|
2月前
|
canal 缓存 NoSQL
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
根据对一致性的要求程度,提出多种解决方案:同步删除、同步删除+可靠消息、延时双删、异步监听+可靠消息、多重保障方案
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
|
3月前
|
关系型数据库 MySQL 数据库
|
3月前
|
存储 机器学习/深度学习 自然语言处理
LangChain与向量数据库:高效的信息检索方案
【8月更文第4天】随着自然语言处理技术的发展,特别是深度学习的进步,我们能够更加高效地处理大量的文本数据。LangChain 作为一种强大的工具链,旨在简化和加速构建复杂的自然语言处理应用程序。结合向量数据库,LangChain 可以实现高效且精准的信息检索功能。本文将探讨这一组合的工作原理,并通过一个具体的实现案例来展示其在实际应用中的效果。
443 2
|
15天前
|
缓存 关系型数据库 MySQL
高并发架构系列:数据库主从同步的 3 种方案
本文详解高并发场景下数据库主从同步的三种解决方案:数据主从同步、数据库半同步复制、数据库中间件同步和缓存记录写key同步,旨在帮助解决数据一致性问题。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
高并发架构系列:数据库主从同步的 3 种方案
|
2月前
|
存储 SQL 关系型数据库
一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
MySQL如何进行分库分表、数据迁移?从相关概念、使用场景、拆分方式、分表字段选择、数据一致性校验等角度阐述MySQL数据库的分库分表方案。
402 15
一篇文章搞懂MySQL的分库分表,从拆分场景、目标评估、拆分方案、不停机迁移、一致性补偿等方面详细阐述MySQL数据库的分库分表方案
|
1月前
|
存储 NoSQL 大数据
大数据-51 Redis 高可用方案CAP-AP 主从复制 一主一从 全量和增量同步 哨兵模式 docker-compose测试
大数据-51 Redis 高可用方案CAP-AP 主从复制 一主一从 全量和增量同步 哨兵模式 docker-compose测试
33 3
|
4月前
|
关系型数据库 MySQL 数据库
|
4月前
|
弹性计算 NoSQL 网络安全
软件开发常见之云数据库Redis连接不上如何解决,修改配置后,需要重启下redis服务,配置才能生效呢,是重启,而不是重载配置,最后导致的问题是点击了的重启,配置修改了之后必须点击重启,而不是修改
软件开发常见之云数据库Redis连接不上如何解决,修改配置后,需要重启下redis服务,配置才能生效呢,是重启,而不是重载配置,最后导致的问题是点击了的重启,配置修改了之后必须点击重启,而不是修改

相关产品

  • 云数据库 RDS