如何用 OBProxy 实现 OceanBase 的最佳路由策略

news/2024/9/19 15:42:19/ 标签: 分布式数据库, oceanbase, 实践经验, 运维管理

引言

OBProxy,即OceanBase Database Proxy,也简称为ODP,是 OceanBase数据库的专属服务代理。通过应用OBProxy,由后端OceanBase集群的分布式特性所带来的复杂性得以屏蔽,从而使得访问分布式数据库的体验如同访问单机数据库一般容易。

OBProxy的核心特性是最佳路由,基本逻辑就是ODP 接收用户发出的 SQL 请求,并将 SQL 请求转发至最佳目标 OBServer 节点,最后将执行结果返回给用户。为了满足客户在不同场景下的路由需求,实现最佳的路由效果,OBPrxoy 支持丰富的路由功能,这就涉及到路由配置项的设置及组合,本文基于业务中一类常见的路由问题展开,对路由功能及对应配置项做详细介绍,指导用户在业务实践中如何正确的配置路由策略及快速排查路由问题。

路由问题

问题描述

只读地址访问到主副本

云客户通过租户的只读地址执行大查询获取数据,结果访问到了主副本,影响了主副本的正常业务。

原因分析

开启了 enable_cached_server 和 enable_primary_zone

在设置 obproxy 的参数 enable_primary_zone = true 和 enable_cached_server =true 的情况下,路由逻辑:

enable_primary_zone= true,用户登录时,会将登录请求发往租户的主副本

enable_cached_server =true,在OBProxy没有解析出表名、表分区计算失败等情况下,请求会复用前一个连接,也就是登录时选择的主副本,这就导致请求无法根据只读地址信息对路由做优化,造成后续的所有请求都发往了主副本。

解决方法

关闭 enable_cached_server 和 enable_primary_zone

路由功能

OBProxy提供了丰富的路由功能,用户可以根据实际需要,设置对应的配置项来控制各种路由策略。

强制路由
  1. 指定IP路由:target_db_server ,OBProxy 将请求直接路由到指定的 OBServer,具有最高优先级,示例:
ALTER PROXYCONFIG SET target_db_server = '127.0.0.1:2993;11.124.5.193:50109';OBProxy收到的所有请求都会路由到127.0.0.1:2993,如果127.0.0.1:2993节点不存在或者故障,则路由到11.124.5.193:50109

2. 指定zone路由:proxy_primary_zone_name,OBProxy 将请求直接路由到指定的 zone,示例:

ALTER PROXYCONFIG SET proxy_primary_zone_name='z2';OBProxy收到的所有请求都会路由到 z2

指定IP路由和指定zone路由,是强制性的路由,不会区分是否强读,适用于不关心Leader位置,需要路由到指定节点的场景。
如果是交易支付等强读业务,希望路由到Leader的场景,需要保强制路由配置项没有设置,避免产生大量远程路由、二次路由等问题。

3. 特定场景强制路由

  • 非分布式事务路由,事务内语句强制路由至事务开启 OBServer 节点
  • 会话级临时表路由,对会话级临时表进行查询时,会强制路由至第一次查询临时表的 OBServer 节点
  • CURSOR/PIECES 路由,客户端使用 CURSOR/PIECES 流式获取/上传数据时,所有请求会强制路由至同一 OBServer 节点
强读路由
  1. 分区表路由

OBProxy 将 SQL 请求中的分区键值或表达式、分区名等条件解析为分区 ID,通过分区 ID 查找到分区的副本位置,将请求路由到Leader副本。

根据分区键值/表达式计算路由,示例:

CREATE TABLE T(C1 INT) PARTITION BY HASH(C1) PARTITIONS 8;SELECT * FROM T WHERE C1=123;
SELECT * FROM T WHERE C1=ABS(123);OBProxy将查询请求路由到对应分区Leader节点

根据分区名计算路由,示例:

CREATE TABLE T(C1 INT) PARTITION BY KEY(C1) PARTITIONS 8;SELECT * FROM T PARTITION(P1);OBProxy将查询请求路由到P1分区的Leader节点

在 OceanBase 数据库中,有 Local 计划、Remote 计划和 Distributed 计划三种表路由。Local 计划、Remote 计划均为单分区的路由。ODP 的作用就是尽量消除 Remote 计划,将路由尽可能的变为 Local 计划。如果表路由类型为 Remote 计划的 SQL 过多,说明该 ODP 的路由可能存在问题,需要排查。

2. 全局索引表路由

配置enable_reroute 和enable_index_route ,OBProxy 将语句中提供的索引值作为分区键来计算路由,示例:

ALTER PROXYCONFIG SET enable_reroute=true;
ALTER PROXYCONFIG SET enable_index_route = true;CREATE TABLE T(C1 INT,C2 INT) PARTITION BY HASH(C1) PARTITIONS 8;
CREATE INDEX INDEX1 ON T(C2);SELECT * FROM T WHERE C2=2;
SELECT * FROM T WHERE C2=2;第一次使用索引查询,将随机路由,OBServer 将返回索引表的 Leader,OBProxy 会构建语句到索引表名称 [SELECT * FROM T WHERE C2=2;] -> [T_INDEX] 的映射
然后进行二次路由,直接获取 T_INDEX 表的映射,计算路由

3. 复制表路由

OBProxy对复制表采用随机路由的策略。示例:

CREATE TABLE T_DUP(C1 INT) DUPLICATE_SCOPE = 'cluster';SELECT * FROM T_DUP WHERE C1=123;OBProxy将查询请求随机路由到T_DUP表的任意副本

4. 计算失败后的路由

当OBProxy 无法获取SQL请求中的表名或者无法通过SQL请求中的条件计算出准确的分区位置信息时,无法准确的强读请求路由到Leader。此时有三种处理策略:

  • 按照租户primary zone路由:enable_primary_zone=True,将请求路由到租户的primary zone
  • 复用上一次的会话路由:enable_cached_server =true,将请求路由到上一个observer会话
  • 随机路由:enable_primary_zone=false 且 enable_cached_server =false,将请求随机路由

示例:

场景一:enable_primary_zone=false && enable_cached_server =trueCREATE TABLE T(C1 INT,C2 INT) PARTITION BY HASH(C1) PARTITIONS 8;SELECT * FROM T WHERE C1=1; 请求准确路由到server1
SELECT * FROM T WHERE C2=1; 无分区条件,无法计算路由,直接将请求路由到上一个会话server1SELECT * FROM T WHERE C1=2; 请求准确路由到server2
SELECT * FROM T WHERE C2=2; 无分区条件,无法计算路由,直接将请求路由到上一个会话server2场景一:enable_primary_zone=true && enable_cached_server =true && leader在server1SELECT * FROM T WHERE C1=1; 请求准确路由到server1
SELECT * FROM T WHERE C2=1; 无分区条件,无法计算路由,直接将请求路由到server1SELECT * FROM T WHERE C1=2; 请求准确路由到server1
SELECT * FROM T WHERE C2=2; 无分区条件,无法计算路由,直接将请求路由到server1
生产和测试环境,一般情况下,建议enable_cached_server设置为false

如果需要分析 OBProxy 的路由策略,可以使用 EXPLAIN ROUTE executable sql 查看 OBProxy路由选取过程。

事务路由

事务路由分两种场景:

  • 分布式事务路由(OceanBase4.1开始支持),事务内的SQL请求准确路由到Leader节点。

配置enable_ob_protocol_v2=true 且 enable_transaction_INTernal_routing = true,示例:

ALTER PROXYCONFIG SET enable_ob_protocol_v2 = true;
ALTER PROXYCONFIG SET enable_transaction_INTernal_routing = true;CREATE TABLE T1(C1 INT,C2 INT) PARTITION BY HASH(C1) PARTITIONS 8;
CREATE TABLE T2(C1 INT,C2 INT) PARTITION BY HASH(C1) PARTITIONS 8;BEGIN;
INSERT INTO T1 VALUES(1,1);路由到server1
INSERT INTO T2 VALUES(11,11);路由到server2
SELECT * FROM T1 WHERE C1=1;路由到server1
SELECT * FROM T2 WHERE C1=11;路由到server2
COMMIT;
事务内的请求都能够准确路由到对应的Leader
  • 非分布式事务路由,事务内SQL请求强制路由至事务开启 OBServer 节点
ALTER PROXYCONFIG SET enable_ob_protocol_v2 = false;
ALTER PROXYCONFIG SET enable_transaction_INTernal_routing = false;CREATE TABLE T1(C1 INT,C2 INT) PARTITION BY HASH(C1) PARTITIONS 8;
CREATE TABLE T2(C1 INT,C2 INT) PARTITION BY HASH(C1) PARTITIONS 8;BEGIN;
INSERT INTO T1 VALUES(1,1);路由到server1
INSERT INTO T2 VALUES(11,11);路由到server1
SELECT * FROM T1 WHERE C1=1;路由到server1
SELECT * FROM T2 WHERE C1=11;路由到server1
COMMIT;
事务内的请求都路由到第一条INSERT的路由节点server1
弱读路由

OBProxy对弱读请求,有两种路由策略:

  • LDC路由,给 OceanBase 集群的每个 Zone 设置地区(Region)属性和机房(IDC)属性,并给 OBProxy 指定机房(IDC)配置项,OBProxy 将 弱读请求按“同机房>同地区>异地”的优先级顺序进行 OBServer 的选取。 通过配置项 proxy_idc_name 控制。 示例:
alter system modify zone "z1" set region = "region1";
alter system modify zone "z1" set idc = "idc1";alter system modify zone "z2" set region = "region1";
alter system modify zone "z2" set idc = "idc2";alter proxyconfig set proxy_idc_name='idc1';CREATE TABLE T(C1 INT,C2 INT) PARTITION BY HASH(C1) PARTITIONS 8;
SELECT /*+READ_CONSISTENCY(WEAK) */ * FROM T;OBProxy会将弱读请求路由到同idc的z1

  • 随机路由,OBProxy将弱读请求随机路由到Leader或者Follower副本,副本优先级由proxy_route_policy控制。对应路由策略:FOLLOWER_FIRST、 FOLLOWER_ONLY、 UNMERGE_FOLLOWER_FIRST。示例:
CREATE TABLE T(C1 INT,C2 INT) PARTITION BY HASH(C1) PARTITIONS 8;
#T表的leader在z1,follower在z2、z3场景一:alter proxyconfig set proxy_route_policy='';SELECT /*+READ_CONSISTENCY(WEAK) */ * FROM T;
OBProxy在z1、z2、z3 三个副本随机选择副本转发弱读请求场景二:alter proxyconfig set proxy_route_policy='FOLLOWER_FIRST';SELECT /*+READ_CONSISTENCY(WEAK) */ * FROM T;
OBProxy优先选择z2、z3 转发弱读请求,如果z2、z3都不可用,则转发到z1场景三:alter proxyconfig set proxy_route_policy='FOLLOWER_ONLY';SELECT /*+READ_CONSISTENCY(WEAK) */ * FROM T;
OBProxy只选择z2、z3 转发弱读请求,如果z2、z3都不可用,则请求报错场景四:alter proxyconfig set proxy_route_policy='UNMERGE_FOLLOWER_FIRST';SELECT /*+READ_CONSISTENCY(WEAK) */ * FROM T;
OBProxy优先选择没在做合并的z2、z3 转发弱读请求

LDC路由的优先级高于随机路由,OBProxy在选择副本的时候,先检查LDC路由,再走随机路由策略。

弱读的路由策略 LDC路由和随机路由,同样适用于计算分区失败的强读路由请求

典型场景

在不同的业务场景,需要综合考虑路由策略配置及优先级,合理配置,来实现指定的路由目标。下面以两个典型路由场景为例,介绍路由功能的应用实践。

读写分离
  • 路由场景

OLTP与OLAP业务混合负载场景下,希望将交易类请求发送到TP副本,将分析型请求发送到AP副本,TP、AP类业务请求需要部署独立的OBProxy,接收AP请求的OBProxy 需要支持将业务的强读请求转换为弱读,并只发送到AP副本。部署架构如图:

  • 路由配置实践

接收AP请求的OBProxy:

设置弱读:alter proxyconfig set obproxy_read_consistency='1';设置路由目标副本:alter proxyconfig set proxy_primary_zone_name='zone_4'; 注意:
确保没有设置过指定ip路由的配置,show proxyconfig like 'target_db_server';

接受TP请求的OBProxy:

ALTER PROXYCONFIG SET enable_cached_server = false;
ALTER PROXYCONFIG SET enable_primary_zone = true;对交易类请求,需要准确路由到分区Leader,如果无法准确计算,则尽力路由到租户的primary zone,减少远程路由OBProxy将交易类请求只发往ZONE_1、ZONE_2、ZONE_3的对应Leader副本注意:
确保没有设置过指定ip路由及指定zone路由
show proxyconfig like 'target_db_server';
show proxyconfig like 'proxy_primary_zone_name';

只读副本
  • 路由场景

OceanBase支持的副本类型,除了全功能型副本,还有只读型副本,简称R副本,R副本只提供读能力,只能作为日志流的 Follower 副本,实际业务中,可以将实时性要求不高的分析类读请求发送到R副本,减轻Leader 副本的压力。

  • 路由配置实践
设置弱读:alter proxyconfig set obproxy_read_consistency='1';设置LDC策略:只读副本同IDC的OBProxy和OBServer设置为相同IDC设置路由策略:alter proxyconfig set proxy_route_policy='FOLLOWER_ONLY';

http://www.ppmy.cn/news/1527301.html

相关文章

macos清理垃圾桶时提示 “操作无法完成,因为该项目正在使用中” 解决方法 , 强制清理mac废纸篓 方法

在macos中,删除文件后, 在清理垃圾桶时提示 “操作无法完成,因为该项目正在使用中” 出现这个提示,在大多数的情况下是因为数据问题导致,需要通过磁盘管理工具进行修复,修复后才可彻底的清理垃圾桶。 另外…

linux重要文件

/etc/sysconfig/network-scripts/ifcfg-eth1 网卡重启 /etc/init.d/network restart ifup ethname & ifdown ethname /etc/resolv.conf 设置Linux本地的客户端DNS的配置文件 linux客户端DNS可以在网卡配置文件(/etc/sysconfig/network/ifcfg-eth0 DNS2)里配置 也可以在/et…

POD内的容器之间的资源共享

概述 摘要:本文通过实践描述并验证了pod内容器如何实现网络、文件、PID、UTC、mount的共享。 pod实战之容器内资源共享与隔离 container容器之间的共享实战 从实际场景说起:有2个容器nginx与wordpress分别运行了紧密耦合且需要共享资源的应用程序。我…

【与C++的邂逅】--- string容器使用

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏: 与C的邂逅 本篇博客我们将来了解string容器本身以及接口的使用。 string是串,本质是一个字符数组,可以对其进行增删查改。 &am…

机器学习--逻辑回归

逻辑回归 前情提要:线性回归 关于分类 C l a s s i f i c a t i o n Classification Classification 在逻辑回归中,我们只讨论 y ∈ { 0 , 1 } y\in\{0, 1\} y∈{0,1} 的情况。其中 1 1 1 表示 p o s i t i v e c l a s s positive \; class posit…

Vue主题色实现

主题色实现 情境 配置平台支持多个主题色的选择,用户可通过在配置平台选择项目主题色。前端项目在骨架屏加载页面获取配置信息,设置项目主题色,实现同个项目不同主题色渲染的需求 实现 1.定义主题色变量 不同主题色根据不同js文件划分定…

‌移动管家手机智能控制汽车系统

‌ 手机可以通过下载特定的应用程序来控制汽车系统,实现远程启动、锁/解锁车门、调节车内温度等功能。‌ ‌ 手机智能控制汽车系统主要通过下载并安装特定的APP来实现。‌ 首先,用户需要确定自己的手机系统是安卓还是苹果版,然后前往应用…

HTML+CSS - 网页布局之多列布局定位

1. 多列布局 CSS中多列布局处理文本内容&#xff0c;特别适合对于长段落或者大量文本进行自动分栏显示 类似于grid分布&#xff0c;但相较之下更加简洁明了 基本语法 <div class"container"><p>这是一些示例文本&#xff0c;当我们使用 column-count…

Python 中常见的数据结构(三)

Python 中常见的数据结构&#xff08;三&#xff09; 9. Heap&#xff08;堆&#xff09; 堆是一种特殊的树形数据结构&#xff0c;Python 中&#xff0c;可以使用 heapq 模块创建一个堆&#xff0c;例如&#xff1a; import heapq numbers [1, 3, 5, 7, 9] heap [] for n…

async Lifetimes

async Lifetimes (Jin Qing’s Column, Sep., 2024) From: https://rust-lang.github.io/async-book/03_async_await/01_chapter.html The Future’s lifetime is bounded by the parameter’s. // This function: async fn borrow_x(x: &u8) -> u8 { *x }// Is equ…

手机、平板电脑编程———未来之窗行业应用跨平台架构

一、平板编程优点 1. 便携性强 - 可以随时随地携带平板进行编程&#xff0c;不受地点限制&#xff0c;方便在旅行、出差或休息时间进行学习和开发。 2. 直观的触摸操作 - 利用触摸屏幕进行代码编辑、缩放、拖动等操作&#xff0c;提供了一种直观和自然的交互方式。 …

codeup:将已有文件夹推送到已有仓库

codeup&#xff1a;将已有文件夹推送到已有仓库 总流程git initgit remote add origin https://codeup.aliyun.com/xxx/xxx.gitgit add .git commit &#xff08;会遇到很多问题&#xff09;git push -u origin master &#xff08;会遇到很多问题&#xff09;成功在仓库中添加…

C++数据结构:以不多于3n/2的平均比较次数在顺序表中找出最大值最小值

题目描述&#xff1a;以不多于3n/2的平均比较次数&#xff0c;在一个有n个整数的顺序表中找到最大值和最小值。要求使用的空间尽可能的少。&#xff08;C实现&#xff09; 从本篇文章开始&#xff0c;我们使用C来实现数据结构的相关问题&#xff0c;本题即是C数据结构的一个基…

C++笔记之类间传参的方法

C++笔记之类间传参的方法 参考笔记: 1.C++笔记之静态成员函数可以在类外部访问私有构造函数吗? 2.C++笔记之设计模式:setter函数、依赖注入 3.C++笔记之两个类的实例之间传递参数——通过构造函数传递类对象的方法详细探究 4.C++笔记之智能指针和单例、依赖注入结合使用 5.…

使用streaming-json-py插件处理JSON数据流:详细指南

目录 一、streaming-json-py简介 二、安装与配置 三、基本使用 示例1:处理不完整的JSON对象 示例2:处理不完整的JSON数组 四、高级用法 实时数据流分析 日志处理 五、性能优化与错误处理 六、总结与展望 在数据驱动的现代社会,实时处理数据流已成为许多应用和服务…

Job定时自动执行SQL日志记录脚本

数据库类型&#xff1a; SQL Server 用途&#xff1a; 用于自动记录SQL当天运行的SQL语句及相关事务&#xff0c;对于DB及业务系统维护人员来说还是很有用的 可解决相关问题&#xff1a; 1、当业务数据表中一条重要数据误删之后&#xff0c;要找回该条数据的插入记录用于恢…

【Linux系统编程】第二十弹---进程优先级 命令行参数 环境变量

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、进程优先级 2.1、什么是优先级 2.2、优先级的描述 2.3、优先级与权限的关系 2.4、为什么要有优先级 2.5、Linux优先级的…

Brave编译指南2024 Windows篇:拉取Brave源码(六)

1.引言 在编译Brave浏览器之前&#xff0c;首先需要获取项目的源码。源码是Brave浏览器的核心组成部分&#xff0c;包含了所有的功能、特性和组件代码。通过获取和管理源码&#xff0c;开发者可以深入了解Brave的实现细节&#xff0c;并进行二次开发和定制化改进。为了确保源码…

【Git】Clone

当git clone失败时&#xff0c;出现 RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: CANCEL (err 8) 错误&#xff0c;可能由于网络连接不稳定或仓库太大导致的。 可以尝试以下几种方法来解决这个问题&#xff1a; 增加 Git 的缓冲区大小&#xff1a; git confi…

go语言的基本语法

学了go语言但是一直没整理。。。那怎么证明我学了&#xff1f;如果学了之后忘了怎么复习&#xff1f;遂诞生这几篇&#xff0c;当作Linux中间的小插曲 整理一下go语言的基本语法&#xff1a; package mainimport ("bufio""fmt""os" ) 在使用对…