在《高性能数据访问中间件 OBProxy(五):一文讲透数据路由》中,我们讲到了数据路由影响因素包括功能因素、性能因素和高可用因素。本文主要介绍高可用因素相关的内容。
相比传统的 IOE 架构,OceanBase 利用更低的成本实现了更高的可用性,为客户提供机器级别容灾、机房级别容灾和城市级别容灾特性,是 OceanBase 数据库的杀手锏之一,深受用户喜欢,因此,本文将对高可用特性展开详细的介绍。
从技术角度看,分布式系统的高可用涉及的模块很多,每个模块都可能出现故障,实现高可用特性是一件非常困难的事情。即使困难很多,OceanBase 数据库还是对外做了 RPO = 0、RTO < 30s 的承诺,这其中涉及到的知识点很多,OBProxy 遇到的问题和 OBServer 也有很大不同,由于本文是 OBProxy 系列文章,所以主要从 OBProxy 的视角去介绍高可用的内容,但 OBServer 的高可用实现也非常精彩,大家也可以多多了解~
OBProxy 高可用的两个维度
了解 OBProxy 高可用特性的实现还得从高可用的概念讲起。“高可用性”(High Availability)通常指一个系统经过专门的设计,从而减少停工时间,而保持其服务的高度可用性。 假设系统可以一直提供服务,那么系统的可用性是100%。如果系统每运行100个时间单位,会有1个时间单位无法提供服务,那么系统的可用性是99%。
我们都知道,单点往往是系统高可用最大的风险和敌人,应该尽量在系统设计的过程中避免单点。从方法论而言,高可用保证的原则是“集群化”,或者叫“冗余”:只有一个单点,该单点挂了会使服务受影响;如果有冗余备份,挂了还有其他备份能顶上。为保证系统高可用,架构设计的核心准则是冗余,只有“冗余”还不够,故障每次出现都需要人工介入恢复一定会增加系统的不可服务实践。因此,我们往往通过“自动故障转移”来实现系统的高可用。
相信你已经从上述内容中了解到 OBProxy 的高可用特性就包含两个维度:一是实现 OBProxy 服务高可用特性,发生故障后可及时恢复 OBProxy 的服务;二是保证 OceanBase 数据库的高可用,如探测和识别 OceanBase 数据库节点的故障并加入黑名单,通过合理路由对应用端屏蔽数据库故障,当数据库节点故障恢复后及时洗白 OBServer 节点,充分利用每一台机器资源。
下面对这两个维度展开详细介绍。
维度一:OBProxy 服务高可用
OBProxy 服务的高可用是指 OBProxy 本身能够连续提供服务,降低故障对代理服务影响。但这会受以下三个因素影响。
-
因素1:部署 OBProxy 的机器是否正常,比如该机器是否可以和其他机器正常通信、机器是否发生了宕机。
-
因素2:OBProxy 进程是否可以稳定运行并正常提供服务,以及进程被误杀后是否可以及时拉起。
-
因素3:OBProxy 依赖的第三方模块如 OCP 和 OBServer 是否正常提供服务,比如 OCP 是否可以正常提供 HTTP 服务。
因素1:部署机器异常
在《高性能数据访问中间件 OBProxy(二):安装部署最佳实践》中我们介绍了 OBProxy 的常见部署方式,我们将通过分析应用端部署和独立部署(OBServer 端部署类似)两种情况下的机器故障介绍 OBProxy 服务高可用,现在我们来回顾一下之前内容。
图1是应用端部署的情况,OBProxy 和业务 App 部署在一台机器上。当业务机器出现问题后,App 和 OBProxy 都会受到影响,需要业务层和 OBProxy一起实现高可用特性。常见的方法有:
-
故障探测:通过第三方系统进行探测、监控、巡检等发现业务服务异常,触发自愈流程后者 SRE 介入。
-
弹性扩展:根据请求量做容量评估,考虑是否需要弹性扩容,如果需要及时扩容,新的机器启动 App 程序和 OBProxy程序提供服务,因为业务 App 和 OBProxy 进程本身无状态,所以扩容一般都很快。
-
流量切换:对故障机器做好隔离,切走流量,转发到其他健康节点服务,保证请求正常执行。
通过上述方法,OBProxy 服务就可以及时恢复。上面步骤时间越短,可用性越高。
图1 应用端部署
和应用端部署不同,独立部署模式下,OBProxy 部署在独立的机器上,同时也引入了负载均衡模块,放在 OBProxy 前面,如图2。
图2 独立部署
这种部署架构下,OBProxy 的高可用和 App 的高可用做了解耦,有多个 OBProxy 提供服务,也就是前面介绍到的冗余。LB 会对 OBProxy 做健康检查,及时发现 OBProxy 的故障,并将故障的 OBProxy 机器拉黑,不再转发 SQL 流量到故障机器。故障后 OBProxy 机器少了,会导致其他 OBProxy 机器的负载增加,如果发现其它机器负载过高,可以添加新的 OBProxy 机器缓解压力。
对比独立部署和应用端部署,我们会发现独立部署出现高可用问题的概率更大,主要原因是链路变长了。举个例子,App 和 OBProxy 出现了网络故障导致服务不可用。在应用端部署的方式下,因为App 和 OBProxy 走本地通信,这种情况几乎不可能出现;而在独立部署方式下,这种问题出现的概率就会大很多。
因素2:OBProxy 进程异常
除了机器故障,OBProxy 进程异常对高可用的影响也很大。产生异常的原因有很多,如程序bug导致进程core、内存使用太多导致OOM(Out Of Memory)、运维操作误杀进程等。虽然原因很多,但最终的表现形式就是服务端口无法提供服务。
对于这种情况,我们通过 obproxyd.sh 脚本解决,你可以回顾《高性能数据访问中间件 OBProxy(二):安装部署最佳实践》,主要原理是通过 nc 命令访问 OBProxy 的监听端口,如果TCP 建连成功就说明 OBProxy 进程存在,如果进程不存在 obproxyd.sh 脚本负责重新启动 OBProxy 进程,OBProxy进程可以在1秒左右启动成功并提供服务。图3为真实环境的进程运行情况,其中的第二个进程为 OBProxy 服务进程,第三个进程为 obproxyd.sh 进程。
图3 OBProxy 进程运行情况
核心代码如下:
function is_obproxy_healthy()
{
echo hi |nc 127.0.0.1 $OBPROXY_PORT -w 2 > /dev/null 2>&1
return $?
}
当然,obproxyd.sh 能做的尽量恢复服务,举个例子,如果程序bug导致一启动就 core,再怎么重启都是无效的,此时可以走机器异常的流程,由负载均衡组件进行处理。但对于概率很小的 bug,重启就可以及时恢复服务,对业务的影响会很小。
因素3:OCP 模块异常
即使 OBProxy 一切正常,但如果依赖的第三方模块异常,那么,OBProxy 也无法正常提供服务。此处我们主要介绍 OCP模块异常。
OCP 为 OBProxy 提供了中心化的配置服务,OCP 保存了一些关键配置信息,如集群名和集群 rslist (OceanBase 总控服务RS 的机器IP列表)的映射关系。当 OBProxy 从 OCP 拉取到 rslist 信息后,会保存本地etc目录下的obproxy_rslist_info.json文件中。
如果 OCP 不可用(通过curl命令访问 OCP 提供的 URL 可以确认),OBProxy 可以使用本地的 rslist 缓存文件提供服务。是否使用缓存文件通过配置项ignore_local_config控制,默认为 true 表示不使用本地缓存。
使用本地缓存可以解决 OCP 异常后的部分集群无法访问的问题,但也存在一定的缺点:
-
缓存中只保存了访问过的集群的 rslist 信息,如果集群未访问还是无法提供服务。
-
缓存信息具有时效性,如果机器的 rslist 变化后则无法感知。
因此,我们需要 OCP 自身是高可用设计的,并在出现问题后及时修复,这样才能保证服务不受影响。
总的来说,通过负载均衡组件和 obproxyd.sh 程序,可以及时处理进程异常和机器异常的情况。OBProxy 在实现时也对程序启动流程做了大量优化,可以在 1 秒内完成初始化和配置加载,并对外提供服务。
OBProxy 尽量减少了对外部模块依赖,但无法做到不使用 OCP 模块,OBProxy 会通过本地缓存的方式降低依赖程度,尽量提高可用性。
维度二:保证 OceanBase 数据库高可用
除了 OBProxy 服务的高可用,OBProxy 一个重要特性就是帮助 OceanBase 数据库实现高可用特性,OBProxy 属于 OceanBase 数据库高可用体系中重要的一环。当 OceanBase 数据库出现问题后,一方面需要数据库系统及时恢复服务;另一方面需要 OBProxy 感知 OBServer 机器故障和服务变更。
OBProxy 要实现上面功能,主要通过故障探测、黑名单机制和 SQL 重试三种手段。故障探测用于发现故障节点,黑名单机制影响 OBProxy 的路由,SQL 重试保证 SQL 尽可能执行成功。
1. 故障探测和黑名单
在讲故障探测前,我们先说明下故障的种类和探测难点。
首先,对于故障的种类,我们主要分为以下两部分。
-
机器和进程故障:如机器宕机、网络故障、进程core等机器硬件问题或进程问题。
-
业务逻辑问题:指 OceanBase 数据库自身逻辑问题导致服务不可用,如 Paxos 选举失败导致无 LEADER 提供服务等。
目前,对于业务逻辑引发故障,与数据库的实现紧密相关,很难去确定问题边界并解决所有问题,比如业务逻辑出现死循环导致服务不可用,OBProxy 是无法解决这种问题的。因此,OBProxy 的策略是在处理 OBServer 机器和进程故障基础上,根据一些已知现象去处理一些业务逻辑问题,如 OBServer 返回的特定错误码(如机器内存不足)、OBServer 长时间无响应等。
说完故障后,我们再讲一下探测相关内容。在分布式系统中,故障探测的结果有三种:成功、失败和超时。其中,超时是最难处理的情况。比如一个 SQL 执行了100秒仍然未返回结果,我们很难确定执行这个 SQL 的 OBServer 是否正常,有时候就是 OBServer 执行慢了,有时候确实是 OBServer 出现问题了;另一方面,探测任务一般都是周期性的,在两次探测之间如果 OBServer 发生了状态变化,OBProxy 无法做到实时感知,因此可能就会使用过期的信息去做一些路由选择,但这样就可能会导致一些慢 SQL 或者 SQL 执行失败。
了解了故障类型和探测难点后,你可以一边往下阅读一边思考 OBProxy 的高可用特性可以处理哪些故障,不能处理哪些故障,以及存在的困难是什么。
我们知道,故障探测的基础是节点状态定义,如定义健康和故障两种状态。但 OBServer 的状态要复杂很多,主要是因为将状态定义更加精细才能实现更多的高可用功能,让客户体验更好。OBProxy 对 OBServer 定义了八种状态。
-
ACTIVE 状态:表示 OBServer 节点正常,可以提供服务。
-
INACTIVE 状态:表示 OBServer 节点异常,无法提供服务。
-
UPGRADE 状态:表示 OBServer 节点正在数据库版本升级阶段。
-
REPLAY 状态:表示 OBServer 节点在进行数据库日志的回放阶段。
-
DELETING 状态:表示 OBServer 节点正在被删除,此时可能正在进行数据迁移等操作。
-
DELETED 状态:表示节点已经被删除,不再属于该集群。
-
DETECT_ALIVE 状态:表示 OBProxy 对 OBServer 节点探测成功,认为 OBServer状态正常。
-
DETECT_DEAD 状态:表示 OBProxy 对 OBServer 节点探测失败,认为 OBServer状态异常。
看到了这么多状态,你是不是感觉记不住,其实只要从原理上思考就会觉得好记很多,如进程core(INACTIVE 状态)、节点下线被删除(DELETING 或者 DELETED 状态)、新增节点(REPLAY 状态)、版本升级(UPGRADE 状态)、进程hang 住(DETECT_DEAD 状态)。
那么根据什么条件设置 OBServer 的状态呢?前6个状态通过访问 OBServer 的内部表获得,OBproxy会周期性(20s/次)从__all_virtual_proxy_server_stat和 __all_virtual_zone_stat表中获取集群的机器状态信息。如下面查询结果展示:
MySQL [oceanbase]> select * from __all_virtual_proxy_server_stat\G
*************************** 1. row ***************************
svr_ip: xx.xx.xx.xx
svr_port: 33041
zone: zone1
start_service_time: 1663664600100327
stop_time: 0
status: active
MySQL [oceanbase]> select * from __all_virtual_zone_stat\G
*************************** 1. row ***************************
zone: zone1
is_merging: 0
status: ACTIVE
server_count: 1
resource_pool_count: 1
unit_count: 1
cluster: ob9988.zhixin.lm
region: sys_region
spare1: -1
spare2: -1
spare3: -1
spare4:
spare5: ReadWrite
spare6:
OBProxy会通过status、start_service_time、stop_time定义OBServer状态。
状态7和状态8通过 OBProxy 的探测机制获得。另外,需要注意的是,发生状态变更后,OBProxy 会根据状态变更结果触发高可用相关的逻辑,许多内容和黑名单机制有关。
展开来讲,就是OBProxy 探测出 OBServer 的节点状态后,先修改黑名单,然后根据黑名单进行节点拉黑或节点者洗白操作。根据不同的探测机制,OBProxy 实现了状态黑名单、探测黑名单和活不可用黑名单三种不同的黑名单。
状态黑名单。状态黑名单依赖于 OBServer 的状态变更。因为历史原因,和状态黑名单相关的状态不包含 DETECT_ALIVE 和 DETECT_DEAD 两种状态,剩下的状态变更都可以通过访问 OBServer 的内部表获得。
当通过周期任务获得 OBServer 最新状态后,OBProxy 会进行图4中的操作。
图4 状态黑名单下,OBServer 状态变更操作
探测黑名单。状态黑名单相当于从“别人”(OceanBase 的总控服务节点 RS)处获得信息,这种信息有时不能反映 OBProxy 和 OBServer 之间的情况。如图5, OBProxy 从 RS 处获得 OBServer1 状态为 ACTIVE,但 OBProxy 和 OBServer1 之间网络不通。
图5 OBProxy 和 OBServer 网络不通的案例
因此,在现有的状态黑名单基础上,我们又实现了探测黑名单,通过给 OBServer 发送探测 SQL 来确定 OBServer 状态。OBProxy 会给 OBserver 的 SYS 租户发送探测 SQL select 'detect server alive' from dual ,并设置5s的超时时间,当超时时间内无结果返回时,会增加一次探测失败次数,当连续失败次数超过3次后,会认为探测失败,设置 OBServer 状态为 DETECT_DEAD。如果有结果返回,会将探测失败次数清零,设置 OBServer 状态为 DETECT_ALIVE。发生探测状态变更后,触发 OBProxy 行为如图6。
图6 探测黑名单下,OBServer 状态变更操作
这里说明下为什么加入到探测黑名单后还会把该 OBServer 的相关连接断开。我们假设不断开和该 OBServer 的连接,那么连接会被一直占用无法发送新的 SQL,在性能数据上会看到这段时间的这台 OBServer 的 TPS 为0,断开后,对于后续请求, OBProxy 会根据黑名单进行路由,不会转发给这台 OBServer,TPS 就可以恢复。
活不可用黑名单。有了状态黑名单和探测黑名单,OBProxy 已经可以很好地处理机器和进程故障了,但 OBProxy 可以更近一步感知每个 SQL 执行失败的原因,去处理更复杂的情况,因此实现了活不可用名单。活不可用名单机制的核心是根据业务 SQL 的执行结果去定义 OBServer 的状态,触发拉黑和洗白操作。主要有以下四个关键步骤。
-
失败:根据时间点记录下一次失败事件。
-
拉黑:在120s 内有 5s 失败记录则拉黑这台 OBServer。
-
尝试:拉黑一段时间后,尝试再次往该 OBServer 发送 SQL。
-
洗白:如果尝试的 SQL 执行成功则进行洗白。
可以看到,活不可用名单的拉黑和洗白谨慎了很多,主要是为了防止一次 SQL 执行结果产生误判。活不可用名单中更复杂的就是对失败事件的定义,可以参考图7。
图7 活不可用名单下,OBServer 状态变更操作
可以看到,上面三种黑名单解决了不同维度的问题,少了任何一个都可能导致某种异常无法处理。对于上述三种黑名单,你可能会想了解它们之间的优先级是什么?你可以认为它们没有优先级,只要 OBServer 在任何一个黑名单中,这台机器就无法接收请求,当 OBServer 不在任何黑名单中才会接收到请求。
对于 HAProxy 等代理,一般只实现了探测机制对后端服务器做健康检查,但这种探测只能解决一些简单的问题。OBProxy 针对 OceanBase 数据库特性,做了更多的工作,如感知 OBServer 版本升级、日志回放、SQL 执行错误等。这是普通代理完全无法做到的。
2. SQL 重试
有了黑名单以后,我们就可以实现 SQL 重试功能,SQL 重试的目的是让 SQL 完成执行,而不是简单把错误抛给客户端。可以进行重试的一个重要原则是不能产生预期外的行为。举个例子,用户执行了 SQL insert into t1 values (c1 + 1, 1),OBServer 很长一段时间没有响应,此时不能重新发给另一台 OBServer,否则有可能导致c1 变成了 c1 + 2。我们要牢记,错误的重试危害更大!
OBProxy 的重试发生在两个阶段,一个是给 OBServer 转发前,一个是给 OBServer 转发后,下面我们来做详细介绍。
转发前重试
我们以 OBProxy 架构图来解释转发前重试,图8的红色部分即为转发前重试的发生位置。
图8 OBProxy 架构图
以一个普通的 SQL select * from t为例说明转发前的重试逻辑。假设 t 为非分区表,表的 partition 的 LEADER 分布在 OBServer1 上面,OBServer1 的 observer 进程 core 掉,RS 发现该机器 core 掉设置内部表状态为 INACTIVE。
根据主副本路由策略,在数据路由阶段选择了 OBServer1 ,然后进行容灾管理检查,发现 OBServer1 在状态黑名单中,此时就进行路由重试,不再走主副本路由,而是走租户内路由,从租户的机器列表中选择机器路由,然后再进行容灾检查,直到容灾检查通过才进行转发。
和所有故障一样,越早发现问题并解决效率越高,转发前重试只发生在 OBProxy 内部,快速的处理了问题,业务几乎无感知。
转发后重试
转发前重试很美好,但依赖黑名单的准确性(参考前面说到的探测难点时效性问题),在分布式系统中,我们无法实时感知机器状态,因此在进行转发前,我们可能还不知道机器发生了问题。此时根据转发的结果可以进行一定程度的重试。
这里你可以想一下,转发结果有哪些?常见结果有两种,一种是 OBServer 机器故障导致 TCP 连接失败,如果无特殊限制(考虑下事务路由),此时可以选择新的机器进行充实;另一种是 OBServer 执行失败返回错误码。因为错误码太过于细节此处就不作详细介绍了,你可以参考 OBProxy 的开源代码ObMysqlTransact::handle_oceanbase_server_resp_error去梳理,举个例子, OBServer 返回错误码 REQUEST_SERVER_INIT_ERROR,此时说明 OBServer 初始化失败,就可以进行重新转发,后续逻辑和转发前重试逻辑很像。
通过转发前重试和转发后重试,OBProxy 处理了大量的 OBServer 问题,整个过程对用户完全透明,用户可能都不知道发生过故障。其中,转发前重试效率高,但依赖黑名单机制;转发后重试是转发前重试一种补充,尽可能地屏蔽后端异常情况。
总之,故障探测、黑名单和 SQL 重试是 OBProxy 高可用特性非常重要的三个功能,三者也有一定的关系。比如转发后重试和活不可用黑名单都依赖 OBServer 的反馈信息,转发前重试依赖黑名单机制。
通过上面三个高可用功能, OBProxy 处理了大部分的 OBServer 异常,如网络故障、OBServer 进程异常、机器宕机等;同时,OBProxy 也进一步识别 OceanBase 数据库本身的一些逻辑异常,如版本升级、日志回放等,让 OBServer 做的更加的好用。
3 和 OceanBase 高可用关系
OBServer 的高可用和 OBProxy 不同,OBServer 基于 Paxos算法,保证在多数派正常情况下就可以正常提供服务,容忍了少数派节点异常。但 OBServer 的高可用可能会导致服务节点从 A 切换到 B(切主操作),因此需要 OBProxy 更快更准的找到正常服务节点。所以两者之间相互配合,对用户提供稳定的服务。
更多 OceanBase 数据库高可用介绍,请参考文档~
高可用测试
高可用听起来是一个高大上的名词,但你也可以通过测试感受一下,当然我们无法在跑业务压测时把机房电源关掉。但对于 OceanBase 数据说的 RTO表现,你也可以用 sysbench 工具(下面测试基于 OBServer 4.0 版本)。方法非常简单,先将 sysbench 压测正常跑起来,然后利用kill -9/-19/-18 操作 OBserver 或者 OBProxy 进程,观察 TPS 的变化。
[ 13s ] thds: 400 tps: 190.00 qps: 3431.03 (r/w/o: 2700.03/380.00/351.00) lat (ms,99%): 1938.16 err/s: 0.00 reconn/s: 0.00
[ 14s ] thds: 400 tps: 452.00 qps: 8034.99 (r/w/o: 6234.99/885.00/915.00) lat (ms,99%): 2045.74 err/s: 0.00 reconn/s: 0.00
[ 15s ] thds: 400 tps: 464.00 qps: 8466.98 (r/w/o: 6591.98/945.00/930.00) lat (ms,99%): 1304.21 err/s: 0.00 reconn/s: 0.00
[ 16s ] thds: 400 tps: 404.00 qps: 7723.98 (r/w/o: 6036.98/865.00/822.00) lat (ms,99%): 1280.93 err/s: 0.00 reconn/s: 0.00
[ 17s ] thds: 400 tps: 515.99 qps: 8798.78 (r/w/o: 6818.83/971.98/1007.97) lat (ms,99%): 1479.41 err/s: 0.00 reconn/s: 0.00
[ 18s ] thds: 400 tps: 546.01 qps: 9694.12 (r/w/o: 7528.10/1071.01/1095.01) lat (ms,99%): 1149.76 err/s: 0.00 reconn/s: 0.00
[ 19s ] thds: 400 tps: 555.99 qps: 9973.84 (r/w/o: 7746.88/1109.98/1116.98) lat (ms,99%): 861.95 err/s: 0.00 reconn/s: 0.00
[ 20s ] thds: 400 tps: 551.02 qps: 10089.34 (r/w/o: 7873.26/1121.04/1095.04) lat (ms,99%): 846.57 err/s: 0.00 reconn/s: 0.00
[ 21s ] thds: 400 tps: 267.00 qps: 4857.99 (r/w/o: 3763.99/534.00/560.00) lat (ms,99%): 831.46 err/s: 0.00 reconn/s: 0.00
[ 22s ] thds: 400 tps: 0.00 qps: 0.00 (r/w/o: 0.00/0.00/0.00) lat (ms,99%): 0.00 err/s: 0.00 reconn/s: 0.00
[ 23s ] thds: 400 tps: 0.00 qps: 0.00 (r/w/o: 0.00/0.00/0.00) lat (ms,99%): 0.00 err/s: 0.00 reconn/s: 0.00
[ 24s ] thds: 400 tps: 0.00 qps: 0.00 (r/w/o: 0.00/0.00/0.00) lat (ms,99%): 0.00 err/s: 0.00 reconn/s: 0.00
[ 25s ] thds: 400 tps: 0.00 qps: 0.00 (r/w/o: 0.00/0.00/0.00) lat (ms,99%): 0.00 err/s: 0.00 reconn/s: 0.00
[ 26s ] thds: 400 tps: 0.00 qps: 211.00 (r/w/o: 90.00/0.00/121.00) lat (ms,99%): 0.00 err/s: 0.00 reconn/s: 178.00
[ 27s ] thds: 400 tps: 3.00 qps: 1765.86 (r/w/o: 1531.88/10.00/223.98) lat (ms,99%): 6594.16 err/s: 0.00 reconn/s: 174.99
[ 28s ] thds: 400 tps: 449.03 qps: 10079.67 (r/w/o: 8246.55/935.06/898.06) lat (ms,99%): 7895.16 err/s: 0.00 reconn/s: 2.00
[ 29s ] thds: 400 tps: 612.00 qps: 10188.00 (r/w/o: 7714.00/1268.00/1206.00) lat (ms,99%): 816.63 err/s: 0.00 reconn/s: 0.00
[ 30s ] thds: 400 tps: 550.03 qps: 10166.58 (r/w/o: 7971.46/1084.06/1111.06) lat (ms,99%): 831.46 err/s: 0.00 reconn/s: 0.00
[ 31s ] thds: 400 tps: 571.96 qps: 10246.31 (r/w/o: 7956.46/1139.92/1149.92) lat (ms,99%): 831.46 err/s: 0.00 reconn/s: 0.00
如上面的数据,TPS 稳定值为500左右,21s ~ 27s 发生了下跌,过程花了7s 左右,对应的就是 RTO < 8s 恢复了服务。
总结
OBProxy 的高可用特性主要包括 OBProxy 服务高可用和保证 OceanBase 数据库高可用两部分,涉及的模块也比较多,任何一个模块出问题都可能牵一发而动全身,可见分布式系统的复杂性。本篇文章也是 OBProxy 路由的重要补充,路由的功能正确性、高性能和高可用都是非常重要的话题。随着 OceanBase 本身架构的演进,高可用特性也需要不断调整,和 OceanBase 数据库做好配合。
从系列文章看,连接管理、路由和高可用彼此关联,相互依赖,你可以花时间多看几遍,这些对理解分布式系统的原理和进行分布式系统设计非常有帮助。