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

news2025/8/8 8:50:19

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

 

Image

图1 应用端部署

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

 

Image

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

Image

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

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

Image

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

Image

图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的红色部分即为转发前重试的发生位置。
Image

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/34386.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【你不知道的javascript上】2. 第三章 全局作用域,函数作用域和块作用域,立即执行函数

预警&#xff1a;【你不知道的javascript】开头的文章&#xff0c;是用来总结书籍《你不知道的Javascript》中我不熟悉的知识&#xff0c;单纯的用来巩固学到的知识&#xff0c;和加深记忆。 可能有些地方我理解的不透彻&#xff0c;所以不能够保证内容的正确性&#xff0c;欢迎…

使用Mysqldump进行定时全备和增备脚本

使用mysqldump进行全备&#xff0c;增备是备份binlog日志 对应的一些变量按照实际环境进行修改即可&#xff0c;如果有更好的思路也可以进行评论交流。 配合计划任务即可完成定时备份的需求&#xff0c;脚本中备份文件存放目录提前创建或者在加个判断进行创建不过我觉得没啥必…

UNIAPP实战项目笔记44 订单页面顶部选项卡 有数据页面样式布局和无数据页面样式布局

UNIAPP实战项目笔记44 订单页面顶部选项卡 有数据页面样式布局和无数据页面样式布局 订单页面顶部选项卡 具体内容图片自己替换哈&#xff0c;随便找了个图片的做示例 具体位置见目录结构 通过 v-show 的false 和 true来切换有无数据页面布局 代码 my-order.vue 页面部分 my-…

[附源码]java毕业设计医院挂号管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

自动化测试定位不到元素怎么办?

1.动态id定位不到元素 分析原因&#xff1a;每次打开页面&#xff0c;ID都会变化。用ID去找元素&#xff0c;每次刷新页面ID都会发生变化。 解决方案&#xff1a;推荐使用xpath的相对路径方法或者cssSelector查找到该元素。 2.iframe原因定位不到元素 分析原因&#xff1a;…

studio3T import a SQL Database to Mongodb(从mysql中导入数据到mongodb)

具体参考studio3T官方文档&#xff1a;Import a SQL Database to MongoDB in 5 Steps | Studio 3T 1、打开SQL Migration-->选择SQL to MongoDB Migration 2、创建源数据库的连接&#xff08;本文源数据库是mysql&#xff09; 3、选择目标数据库 默认选择当前连接的数据库…

【观察】OceanBase社区版4.0:引领时代,更创造时代

今年8月10日&#xff0c;在2022 OceanBase年度发布会上&#xff0c;OceanBase 4.0首次亮相&#xff0c;在经过85天的快速升级迭代&#xff0c;且历经内外部客户的场景测试与真实业务场景的稳定性“打磨”之后&#xff0c;OceanBase 4.0将“简单易用”的应用感受留给了客户。而在…

JS中的setter、getter数据存取器

JS属性可分为两种类型 ① 数据属性    只是简单存储了一个值 ② 存取器属性    最大的特点是在设置、获取属性值的时候能够做一些其他的操作 设置存取器属性的两种方式 ① 直接在对象中设置 let obj {count: 5, // 普通的数据属性// index为存取器属性_index: 1, // _in…

Linux系统上搭建Java的运行环境,并且部署JavaWeb程序

Linux系统上搭建Java的运行环境&#xff0c;并且部署JavaWeb程序 1.JDK 基于yum【包管理器】来进行安装即可。 yum list列出应用商店上所有的软件包名字。 yum list | grep jdk验证安装成功&#xff01;&#xff01; 2.Tomcat 由于yum商店里的tomcat的版本过低&#xff0…

SpringBoot SpringBoot 原理篇 1 自动配置 1.6 bean 的加载方式【四】

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 原理篇 文章目录SpringBootSpringBoot 原理篇1 自动配置1.6 bean 的加载方式【四】1.6.1 Import1 自动配置 1.6 bean 的加…

正大数据周五新鲜报 做期货要关注哪块消息?

正规的外盘期货公司都是在香港证监会的监管下&#xff0c;持有合法合规金融牌照。这点好比国内证券和期货公司在中国证监会的监管下一个道理&#xff0c;完全正规合法。 ​ ​如果你是想做主账户往下开展业务&#xff1a; 一、进入香港证监会官网查询该期货公司的编号 二、…

Spring 中 Bean 的作用域和生命周期

目录 1. Bean 的作用域 1.1 Bean 的六大作用域 1.1.1 单例作用域 (singleton) 1.1.2 原型作用域 (prototype) 1.1.3 请求作用域 (request) 1.1.4 会话作用于 (session) 1.1.5 全局作用于 (application) 1.1.6 HTTP WebSocket 作用域 (websocket) 1.2 如何设置 Bean 的…

142.如何个性化推荐系统设计-2

142.1 离线训练 离线训练流程 如何线上实时反馈特征&#xff1f; 在线计算&#xff0c;与曝光日志一起上报&#xff0c;离线直接使用 如何解决曝光不足问题&#xff1f; 使用CTR的贝叶斯平滑&#xff08;CTR 曝光次数 / 点击次数&#xff09; 所有新闻自身CTR服从Beta分布: 某…

199道SpringCloud面试题,你能答上来吗

前言 Spring Cloud Alibaba 是阿里中间件团队主导的一个新生项目&#xff0c;正处于高速迭代中。 其次&#xff0c;对于中国用户来说&#xff0c;Spring Cloud Alibaba 还有一个非常特殊的意义&#xff1a;它将曾经红极一时的 Dubbo&#xff0c;以及阿里巴巴的强力消息中间件…

每天花2小时复习Java面试指南,高级架构视频,我进了阿里定级P7

Java进阶架构师必备 基础 容器 并发 JVM Java8 计算机网络 计算机操作系统 Linux 数据结构 算法 mysql (优化思路) 系统设计 分布式 线上问题调优(虚拟机&#xff0c;tomcat) 面试指南 工具 ​ 编辑 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&…

用Python采集球员信息,成功预测到了球赛胜负?

前言 嗨嗨&#xff0c;最近看球赛的朋友多吗 emm怎么说&#xff0c;我对这个虽然兴趣不是很大 但是还是想跟朋友赌赌&#xff0c;自己对这些球员也不是很熟悉&#xff0c;索性叫我的好同事帮我用Python采集了各国球员的一些信息&#xff0c;没料到竟预测成功了&#xff01; …

2022 谷歌出海创业加速器展示日: 见证入营企业成长收获

经历三个月的沉淀&#xff0c;迎来了展示日的大放异彩。10 家入营企业的路演分享&#xff0c;带来诸多启发 ——企业出海有什么挑战和难点&#xff1f;加入谷歌出海创业加速器&#xff0c;团队有哪些收获&#xff1f;三个月的培训和交流&#xff0c;带来了怎样的感受&#xff1…

Vue中插槽slot

slot插槽&#xff08;别名&#xff1a;内容分发&#xff09;&#xff1a; 作用&#xff1a; 混合父组件的内容与子组件自己的模板&#xff1b;父组件模板内容在父组件作用域内编译&#xff1b;子组件模板的内容在子组件作用域内编译&#xff1b;扩展组件能力&#xff0c;提高…

VGG16 -19 — CV 中表现最好的 ConvNet 模型

从先进的计算机视觉出现的 Alexnet 开始&#xff0c;人们开始尝试不同的架构。牛津大学工程科学系的 Karen simonyan 和 Andrew Zisserman 在对 ImageNet Challenge 2014 的数据集进行了一些实验后提出了非常深的卷积网络&#xff1a;VERY DEEP CONVOLUTIONAL NETWORKS FOR LAR…

美食杰项目(二)首页

目录前言具体样式代码思路加载样式相应组件相应代码总结&#xff1a;前言 本节给大家讲的是美食杰项目的首页的主要功能和具体样式 具体样式 代码思路 1.点击首页跳转到首页页面 2.在父组件将轮播图所需的图片请求出来&#xff0c;再传给轮播组件 3.在父组件将商品列表的数据…