ODP 背景知识
如果大家对 OceanBase 的 ODP(OceanBase Database Proxy)组件尚不了解,在阅读社区版 ODP 问题排查手册之前,建议先快速浏览这篇文档,以了解 ODP 相关的背景知识。
如果时间紧迫,可以只阅读本文最开始的 “ODP 的特性” 和 “ODP 路由的实现逻辑” 这两个部分。
ODP 的故障排查脑图
如果大家已经了解 ODP,只想对在 ODP 使用过程中遇到的问题进行排查,可以参考下面这张图片,跳转到后面几个小节进行阅读。
ODP 是什么
ODP 是代理服务器,代理服务器会让访问数据库的链路多一跳,那为什么需要 ODP 呢?我们以下图为例进行说明。
图中 APP 是我们的业务程序,APP 下面有三台 ODP(ODP 的进程名叫做 obproxy),在实际部署中,ODP 和 APP 之间一般会有一个负载均衡(如 F5、LVS 或 Nginx 等)将请求分散到多台 ODP 上面,ODP 下面是 OBServer 节点,图中有 6 个 OBServer 节点。
需要使用 ODP 的原因如下:
-
数据路由
ODP 可以获取到 OBServer 节点中的数据分布信息,可以将用户 SQL 高效转发到数据所在机器,执行效率更高。例如,对于
insert into t1 where c1 in P1
语句 ODP 可以将 SQL 转发到 Zone 2 中含有 P1 主副本的机器上。对于update t1 where c1 in P2
语句 ODP 可以将 SQL 转发到 Zone 1 中含有 P2 主副本的机器上。 -
连接管理
如果一个 OceanBase 集群的规模比较大,那么运维机器上、下线以及机器出现问题的概率也会相应增大。如果直连 OBServer 节点,遇到上面的情况,客户端就会发生断连。ODP 屏蔽了 OBServer 节点本身分布式的复杂性,客户连接 ODP,ODP 可以保证连接的稳定性,自身对 OBServer 节点的复杂状态进行处理。
也就是说,ODP 可以实现像使用单机数据库一样使用分布式数据库。
ODP 的特性
作为 OceanBase 数据库的关键组件,ODP 具有如下特性:
-
高性能转发
ODP 完整兼容 MySQL 协议,并支持 OceanBase 自研协议,采用多线程异步框架和透明流式转发的设计,保证了数据的高性能转发,同时确保了自身对机器资源的最小消耗。
-
最佳路由
ODP 会充分考虑用户请求涉及的副本位置、用户配置的读写分离路由策略、OceanBase 数据库多地部署的最优链路,以及 OceanBase 数据库各机器的状态及负载情况,将用户的请求路由到最佳的 OBServer 节点上,最大程度的保证了 OceanBase 数据库整体的高性能运转。
-
连接管理
针对一个客户端的物理连接,ODP 维持自身到后端多个 OBServer 节点的连接,采用基于版本号的增量同步方案维持了每个 OBServer 节点连接的会话状态,保证了客户端高效访问各个 OBServer 节点。
-
安全可信
ODP 支持使用 SSL 访问数据,并和 MySQL 协议做了兼容,满足客户安全需求。
-
易运维
ODP 本身无状态支持无限水平扩展,支持同时访问多个 OceanBase 集群。可以通过丰富的内部命令实现对自身状态的实时监控,提供极大的运维便利性。
ODP 社区版完全开源,使用 MulanPubL - 2.0 许可证,用户可以免费复制和使用源代码,修改或分发源代码时,请遵守木兰协议。
ODP 路由的性能因素
高性能是 OceanBase 数据库的重要特性,路由对性能的影响主要在网络通信开销方面。ODP 通过感知数据分布和机器地理位置降低网络通信开销,提高整体性能。第七章是介绍 SQL 性能诊断和调优的章节,所以我们这一小节主要会从性能方面对路由策略进行介绍。
我们首先会介绍三个背景知识:
-
ODP 路由的实现逻辑是什么?
-
SQL 主要的计划类型有哪些?
-
如何查看资源分布信息?
ODP 路由的实现逻辑
路由是 OceanBase 分布式数据库中的一个重要功能,是分布式架构下,实现快速访问数据的利器。
Partition 是 OceanBase 数据存储的基本单元。当我们创建一张 Table 时,就会存在表和 Partition 的映射。非分区表中,一张 Table 对应一个 Partition;分区表中一个 Table 会对应多个 Partition。
路由实现了根据 OBServer 节点的数据分布精准访问到数据所在的机器。同时还可以根据一定的策略将一致性要求不高的读请求发送给副本机器,充分利用机器的资源。路由选择输入的是用户的 SQL、用户配置规则、和 OBServer 节点状态,路由选择输出的是一个可用 OBServer 地址。
其路由实现逻辑如下图所示:
-
解析 SQL 并提取信息
解析 SQL 模块使用的是 ODP 自己定制的 Parser 模块,只需要解析出 DML 语句中的数据库名、表名和 Hint,不需要通过其他复杂的表达式推演。
-
通过 location cache(路由表)获取位置信息
ODP 根据用户的请求 SQL 获取该 SQL 涉及的副本位置。ODP 每次首先会尝试从本地缓存中获取路由表,其次是全局缓存,如果都没有获取到,最后会发起异步任务去向 OBServer 节点查询路由表。对于路由表的更新,ODP 采用触发更新机制。ODP 每次会把 SQL 根据路由表转发给相应的 OBServer 节点,当 OBServer 节点发现该 SQL 不能在本地执行时,会在回包时反馈给 ODP。ODP 根据反馈决定下次是否强制更新本地缓存路由表。通常是在 OBServer 节点合并或者负载均衡导致切主时,路由表才会发生变化。
-
确定路由规则
ODP 需要根据不同情况确定最佳的路由规则。比如:强一致性读的 DML 请求期望发到分区主副本所在的 OBServer 节点上,弱一致性读的 DML 请求和其他请求则不要求,主副本和从副本均衡负载即可。如果 OceanBase 集群是多地部署,ODP 还提供了 LDC 路由,优先发给同机房的 OBServer 节点,其次是同城的 OBServer 节点,最后才是其他城市的 OBServer 节点。如果 OceanBase 集群是读写分离部署,ODP 还提供了读 Zone 优先、只限读 Zone、非合并优先等规则供业务按照自身特点配置。上述的几种情况在路由选择中是组合关系,输出是一个确定的路由规则。
-
选择目标 OBServer 节点
根据确定的路由规则从获取的路由表中选择最佳的 OBServer 节点,经过黑名单、灰名单检查后,对目标 OBServer 节点进行请求转发。
SQL 的计划类型
分区(Partition)是数据存储的基本单元,当我们创建表时,就会存在表和分区的映射。如果是非分区表,一张表仅对应一个分区,如果是分区表,一张表可能会对应多个分区。每个分区根据副本角色又分为一个主副本和多个备副本,默认读写的都是分区的主副本。
在 OceanBase 数据库中,SQL 在执行前会生成一个执行计划,执行器根据这个执行计划来调度不同的算子完成计算。计划主要分为三种不同的类型,分别是本地(Local)计划、远程(Remote)计划和分布式(Distributed)计划。
下面以 OceanBase 数据库默认的强一致性读为例,介绍这三种不同的计划类型,即查询过程中需要访问分区的主(Leader)副本。
本地计划
本地计划表示语句所涉及的所有分区的主副本都在当前 Session 所在的 OBServer 节点上,整条 SQL 在执行过程中,不需要和其他 OBServer 节点再进行额外地交互。