高性能数据访问中间件 OBProxy(六):一文讲透数据路由

在《高性能数据访问中间件 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 服务就可以及时恢复。上面步骤时间越短,可用性越高。

 

高性能数据访问中间件 OBProxy(六):一文讲透数据路由_第1张图片

图1 应用端部署

和应用端部署不同,独立部署模式下,OBProxy 部署在独立的机器上,同时也引入了负载均衡模块,放在 OBProxy 前面,如图2。

 

高性能数据访问中间件 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 进程。

 

Image

图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中的操作。

高性能数据访问中间件 OBProxy(六):一文讲透数据路由_第3张图片

图4 状态黑名单下,OBServer 状态变更操作

探测黑名单。状态黑名单相当于从“别人”(OceanBase 的总控服务节点 RS)处获得信息,这种信息有时不能反映 OBProxy 和 OBServer 之间的情况。如图5, OBProxy 从 RS 处获得 OBServer1 状态为 ACTIVE,但 OBProxy 和 OBServer1 之间网络不通。

高性能数据访问中间件 OBProxy(六):一文讲透数据路由_第4张图片

图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。

Image

图6 探测黑名单下,OBServer 状态变更操作

这里说明下为什么加入到探测黑名单后还会把该 OBServer 的相关连接断开。我们假设不断开和该 OBServer 的连接,那么连接会被一直占用无法发送新的 SQL,在性能数据上会看到这段时间的这台 OBServer 的 TPS 为0,断开后,对于后续请求, OBProxy 会根据黑名单进行路由,不会转发给这台 OBServer,TPS 就可以恢复。

活不可用黑名单。有了状态黑名单和探测黑名单,OBProxy 已经可以很好地处理机器和进程故障了,但 OBProxy 可以更近一步感知每个 SQL 执行失败的原因,去处理更复杂的情况,因此实现了活不可用名单。活不可用名单机制的核心是根据业务 SQL 的执行结果去定义 OBServer 的状态,触发拉黑和洗白操作。主要有以下四个关键步骤。

  • 失败:根据时间点记录下一次失败事件。
  • 拉黑:在120s 内有 5s 失败记录则拉黑这台 OBServer。
  • 尝试:拉黑一段时间后,尝试再次往该 OBServer 发送 SQL。
  • 洗白:如果尝试的 SQL 执行成功则进行洗白。

可以看到,活不可用名单的拉黑和洗白谨慎了很多,主要是为了防止一次 SQL 执行结果产生误判。活不可用名单中更复杂的就是对失败事件的定义,可以参考图7。

高性能数据访问中间件 OBProxy(六):一文讲透数据路由_第5张图片

图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的红色部分即为转发前重试的发生位置。
高性能数据访问中间件 OBProxy(六):一文讲透数据路由_第6张图片

图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 数据库做好配合。

从系列文章看,连接管理、路由和高可用彼此关联,相互依赖,你可以花时间多看几遍,这些对理解分布式系统的原理和进行分布式系统设计非常有帮助。

你可能感兴趣的:(oceanbase)