http://www.tuicool.com/articles/beYZfi7
引言
高可用(High Available)是线上生产环境所必不可少的重要条件,阿里云数据库Redis版作为一款成熟稳定的数据库产品,针对Redis的特性也支持高可用,本文将介绍云Redis是如何实现这一方案。
架构
目前云Redis有主从版和集群版两种架构,本次主要针对主从版做HA的解析,集群版HA只在最后切换VIP指向时稍有不同,但均可保证高可用性。
下图为主从版架构:
由图可知,云Redis实例有主备两个节点,平时只有Master提供服务,Slave只做热备不提供访问,Slave通过slaveof命令不断从Master接收数据,保证Master宕机时云Redis仍可提供服务。
每一个云Redis实例都会分配一个VIP并与DNS绑定,VIP经过SLB后直接访问Master不再有其他中间层,访问Redis的链路为DNS-->VIP-->SLB-->REDIS(MASTER)。
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" /* 连接超时,目前设置为18秒 */ "connect timed out" /* 读取数据超时,目前设置为2分钟 */ "Read timed out" /* Redis正在加载数据 */ "LOADING Redis is loading the dataset in memory" /* 访问的Redis是Slave */ "READONLY You can't write against a read only slave"
关于为何将读超时设置为2分钟这么久呢,这是我们在日常运维处理各种问题时,根据总结出来的经验设置的一个相对合理的大小。
在一开始时读超时的时间设置的和连接超时同样为18秒,结果线上经常会有HA发生主备切换,这是因为Redis处理客户端命令的线程只有一个,当在处理一些耗时操作比如FLUSHALL、KEYS等命令时,执行时间可达数十秒甚至几分钟,此时Redis处于"假死"状态造成误切换。经测试,清空64G的数据大约需要2分钟的时间(目前主从版云Redis最大实例规格即为64G),故将读超时设置为2分钟。
单纯调整超时时间并不是我们的最终方案,这里仍在改进,比如增加一个状态监测端口,新开一个状态线程来探测Redis活性等,欢迎大家集思广益提供优质解决方案。
主备切换前准备工作
当健康检查发现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%,仅在主从都发生宕机的极端情况无法服务。
结束
本文介绍了云数据Redis版HA方案,通过主从双机热备来保证服务高可用,健康检查出现异常时及时进行主备切换,有效保障业务运行。