| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> 高性能数据访问中间件 OBProxy(五):一文讲透数据路由 -> 正文阅读 |
|
[大数据]高性能数据访问中间件 OBProxy(五):一文讲透数据路由 |
上篇文章我们介绍了 OBProxy 的连接管理,通过连接管理功能,OBProxy 和 OBServer 联系起来,同时 OBProxy 屏蔽了连接的复杂性,让用户使用起来和单机数据库一样简单。完成接入后,接下来的一个重要功能就是数据路由,这也是大部分用户最关心的功能之一,本文会对其进行详细介绍。 在介绍 OBProxy 的路由原理前,我们先讨论下路由需要考虑的影响因素,方便你更好地理解后面的内容,以及评价一个路由功能的好坏。我将从功能、性能和高可用三个因素展开介绍。 数据路由影响因素功能因素你是否考虑过,一个单机数据库的功能如 MySQL 数据库的 Prepared Statements 功能,在分布式系统中该如何实现,比如 PREPARE Statement 和 EXECUTE Statement 该发往哪个节点? 我们以 Prepared Statements 功能为例说明功能对路由的影响。Prepared Statements 执行主要有两个步骤:
步骤二是依赖于步骤一的,我们假设执行情况如图1所示,你就会明白,当 OBServer2 收到步骤二( EXECUTE)的请求后,并不知道步骤一(PREPARE)请求的内容,这时,OBServer2 就会报错(优雅做法)或断连接(粗暴做法)。
对于这种问题,常见的解决办法有两种(见图2)。
图2 解决路由失败的两个方法 性能因素高性能是 OceanBase 数据库的重要特性,路由对性能的影响主要是延迟,即网络通信开销。OBProxy 通过感知数据分布和机器地理位置降低网络通信开销,提高整体性能。 数据分布主要影响执行链路的跳数,OBProxy 路由时直接命中数据所在的节点是最好的。我们以 SQL 语句 机器地理位置主要影响网络延迟,当选择了一个远端节点后,SQL执行会变慢,有时网络延迟的时间比数据库执行时间要大很多。我们在阿里云上做了测试,延迟数据如下:
可以看到跨可用区后延迟增加接近2ms,对于简单SQL,数据本身执行时间可能才100us左右。因此,**对于不同地理位置的机器,OBProxy 选择优先级是:同机房>同城不同机房>不同城市。**图4展示了优先选择同城市的OBServer1。图4 优先选择同城市的OBServer1 高可用因素高可用因素是指 OceanBase 数据库对机器故障有容忍能力,让故障对应用透明无感知,**OBProxy 发现 OBServer 节点故障后,路由时会排除故障节点,选择健康节点,对于正在执行的SQL也有一定的重试能力。**高可用涉及故障探测、黑名单机制、重试逻辑等内容。如图5所示,OBProxy 发现OBServer1 故障后,将该节点加入黑名单。路由时从健康节点选择。 了解了数据路由的影响因素和路由原则后,我们就可以更高效地进行路由策略设计了。不过,现实情况会复杂很多,原则上我们要实时感知 OBServer 状态、数据分布等,但在工程实践中很难做到,便引发出许多问题。因此,我们在**考虑路由时需要兼顾功能、性能和高可用,**让 OceanBase 数据库“更好用”。 OBProxy 路由功能我们知道通过 OBProxy可以访问不同集群的不同租户的不同机器。这也是 OBProxy 可以实现集群路由、租户路由和租户内路由的原因,接下来我将围绕这三部分介绍OBProxy的路由功能。 集群路由集群路由是指 OBProxy 路由功能支持访问不同的集群,它的关键点在于获取集群名和rslist的映射关系(见图6):
需要注意的是,**这里的rslist不需要包含所有的集群机器列表,OBProxy 会通过访问内部表获取集群所有机器,**一般rslist为RootServer(OceanBase的总控服务)所在的机器。图6 集群路由步骤 我们从图6中可以看到,OCP 是集群路由时非常重要的一个模块。当出现集群路由问题时,大部分都是 OCP 模块出现了问题,常见等问题有两个。
OBProxy 是在用户登录首次访问集群时获取rslist,并保存到内存中,后续再访问该集群,从 OBProxy 的内存中获取就可以了。这里需要注意,当集群内存信息创建好后,OCP再出现问题,即使OBProxy 仍可以正常工作,也要及时排查 OCP 问题。 租户路由OceanBase 数据库中,一个集群有多个租户,租户路由是指 OBProxy 路由功能支持访问不同的租户。在众多租户中,sys租户比较特殊,类似于管理员租户,和集群管理相关。我们将分开讨论sys租户路由和普通租户路由。 1. sys租户路由完成集群路由后,我们可以获得集群的rslist,此时 OBProxy 会通过proxyro@sys账号登录rslist中的一台机器,并通过内部表 OBProxy 会15秒访问一次 除了集群机器列表,OBProxy 还会通过sys租户获取partition分布信息、zone信息、租户信息等。可见sys租户对 OBProxy 非常的重要。 2. 普通租户路由sys租户的路由信息就是集群的机器列表,但普通租户不同,普通租户路由信息就是租户资源(unit是CPU、内存、磁盘等资源载体,详情可查阅 OceanBase 数据库名词概念)所在的机器。 注意:由于历史原因,查询租户路由信息并不是通过unit相关的表,而是通过特殊表名 图7 普通租户路由信息 当获取到租户信息后,OBProxy 会保存在本地内存中,并根据一定策略进行缓存信息的更新。对于 sys 租户,通过15秒一次的拉取任务获得最新的信息;对于普通租户,而刷新频率并不高,普通租户的路由缓存策略如下。
总的来说,在多租户架构下,OBProxy 通过 sys 租户获得元数据信息,sys租户本身路由信息就是集群的机器列表,然后通过元数据信息获得租户的路由信息。通过租户路由功能,OBProxy 支持了 OceanBase 数据库的多租户架构。 租户内路由租户内路由是指在获取租户的机器列表后,选择合适的节点执行SQL。 对于租户内路由,OBProxy 可以像普通代理如 HAProxy 一样,一个客户端连接对应一个服务端连接,服务端机器从租户机器列表选取,这样功能就会简单很多,但无法满足性能和高可用要求,可见路由影响了连接管理。 租户内路由是路由功能最复杂的部分,主要原因是在想办法提供更好的性能和更高的可用性。我将按照主副本路由、备副本路由、租户机器路由、缓存信息、路由策略、事务路由和常见问题这七部分为你介绍。为什么是这样的顺序呢?你可以在阅读完本文后尝试梳理思维导图,感受更深。 1. 主副本路由在分布式系统中,为了容灾高可用,会采用多副本机制。副本之间需要保证数据一致性,往往采用Paxos或者Raft算法,在工程实践中,有一个特殊副本,该副本数据最新,并控制数据在副本间的同步,这个副本叫做主副本,其它副本叫做备部分。 由于 OceanBase 数据库只有一个主副本,因此,主副本路由策略就是发往该副本。我们以
在 OBProxy 日志中,主副本路由的关键字是 对于多分区路由,涉及分区方式(如hash、range和list)、分区键类型(number、varchar等)、分区算法(如hash算法)、类型转换(如SQL中的值类型和分区键类型不同)等知识点,实现比较复杂,我们以二级分区为例介绍,分为10个步骤(见图8)。 图8 多分区路由流程 2. 备副本路由了解完主副本路由策略后,你一定想到了备副本路由。备副本路由也需要满足两个条件:SQL语句查询实体表,上面例子是t1表;请求要求弱读即可。 这两个条件和主副本路由需要满足的条件是有区别的:
对于备副本路由,发往主副本和备副本都可以正常工作,因此备副本路由可以选择变多了**(**对于多个副本选择的问题,请参考下文“路由策略”的内容)。在很多时候,你可能认为备副本路由只能发往备副本,而实际上发往主副本也可以正常工作。 和备副本相关的一个重要话题就是读写分离,请求进行读写分离后,可以降低主副本压力,是一个很好用的功能。OBProxy 也实现了读写分离功能,并在不断打磨细节,在 OceanBase 公有云等场景帮助客户解决了性能问题。 3. 租户机器路由有些时候我们无法获取主副本或备副本,此时就可以从租户机器中选取一台,这就是租户机器路由。
通过租户机器路由,OBProxy 将 SQL 发往了租户所在的机器,因此可以保障功能正常。租户机器路由和备副本路由一样,有多个副本可以选择,也存在着路由策略的问题。 4. 缓存信息主副本路由、备副本路由和租户机器路由都需要通过sys租户查询副本路由信息,为了提升性能和降低对sys租户的压力,OBProxy 对路由信息做了缓存。对于缓存信息,最重要的是时效性。你可以对比sys租户的缓存信息更新,sys租户的缓存信息可以通过定期访问内部表创建和刷新,那么副本路由的缓存信息是否可以采用此策略呢? 答案是:不可以。主要问题是拉取副本路由信息的SQL太多,会对sys租户造成很大的压力。SQL的数量 = 副本的个数 * OBProxy的数量。 OceanBase 数据库可以支持十万、百万分区,分区数极大。OBProxy 的数量受到部署架构影响,部署在应用端形态下,数量也很多。因此,缓存时效性对 OBProxy 是一大难题,使用了过期的缓存信息就会出现大家常说的“路由不准”的问题。那么,怎么保证缓存的时效性呢? 我们先看一下缓存信息在 OBProxy 中的内容。使用root@proxysys账号登录,通过show proxyroute命令可以查看表的缓存信息,如下:
这个例子展示了缓存包含的重要信息:集群名、租户名、库名、表名、分区数、副本数、时间、地址信息和缓存状态等。其中,缓存状态是需要我们重点关注的对象,缓存策略都是通过修改状态信息实现的,这些状态影响缓存的刷新机制。缓存信息分为如下5个状态。
我们通过修改缓存状态就能刷新缓存状态,从而保证时效性,下面从创建、淘汰和刷新这三方面介绍缓存刷新机制。
目前缓存淘汰主要通过 OBServer 的报文反馈实现,这样就无法实时感知,只有出现一次“错误”路由后,才能刷新,这也是容易出问题一个地方。 5. 路由策略5.1 路由策略介绍路由策略用于从多副本中选择出一个合适的副本。这里的多副本,可能来自备副本路由时选择出的多个副本,也有可能是类似 路由策略主要有三种:LDC路由、Primary Zone路由和随机路由,路由策略优先级为 Primary Zone路由 > LDC路由 > 随机路由。 **1)Primary Zone路由。**在多副本选择时,优先发往Primary Zone(租户的属性,Primary Zone指副本的Leader优先分布在Primary Zone中)所在的机器。为什么会有这种路由策略?首先,OceanBase 中常用的高性能部署架构是租户的 Primary Zone 在一台机器,这样可以避免分布式系统的很多网络开销;其次,OBProxy 在主副本路由时,存在找不出表名和计算不出分区的情况,通过Primary Zone路由可以尽量发往主副本。 2)LDC路由是基于地址位置的路由,有两个重要的概念:IDC和Region。IDC表示逻辑机房概念,Region是城市的概念。OBProxy 和 OBServer 都可以设置LDC信息。通过LDC信息,OBProxy 可以确定和 OBServer 的位置关系。当我们设置了LDC信息后,OBProxy就会默认使用LDC路由。
OBserver 的每个Zone都可以设置Region属性/idc属性,Region通常代表城市的概念,通常设置为城市名(大小写敏感),IDC代表该Zone所处的机房信息,通常设置机房名(小写)。设置SQL如下:
OBProxy通过配置项或者启动参数设置LDC信息。首先通过-i选项设置启动参数,然后执行配置项:执行SQL语句 图10 OBProxy设置LDC 你一定在想有没有最佳实践,确实有。如果只有一个机房,LDC用处不大,因为我们认为同机房机器间延迟相同。如果在同机房要使用LDC,需要划分出LDC架构,并设置 OBServer 和 OBProxy 的LDC属性。如果有多个机房,就可以根据机房和城市设置LDC,如公有云杭州可用区I、H机房,它们Region相同,IDC名字不同。 某些特殊情况下,可以通过trick方法设置LDC影响LDC路由,但不太推荐你这么做。 **3)随机路由。**通过优先级路由后,如果还有多个副本,进行随机路由即可。如未开启Primary Zone路由或者未设置LDC路由,就会直接使用随机路由。 5.2 路由配置和查看数据路由比较复杂的一个原因是有不同的路由策略,OBProxy默认策略是先进行主副本路由和备副本路由,没有副本则进行租户机器路由。如果只有一个副本被选中,则直接路由,否则根据策略路由。 对于 Primary Zone 路由和 LDC路由,受到配置项控制:
除了现有路由策略,有时我们想使用其它路由策略,可以通过修改配置项
OBProxy 具体使用了什么路由策略,可以在 OBProxy 的日志中查看关键信息
对于该问题,你也可以参考《高性能数据访问中间件 OBProxy(三):问题排查和服务运维》。 6. 事务路由上面介绍了单个SQL的路由策略,有些功能如事务功能包含一条或多条SQL。对于事务路由,事务的第一条语句受到上述策略影响,后续SQL不再进行路由,直接发往第一条语句发往的节点。 为什么事务路由只能发往第一条语句发往节点?你可以参考数据路由影响因素中的“功能因素”。目前我们还未实现事务状态迁移,所以有此限制。 7. 常见问题相信当你看到限制要求后,感觉到此处可能有坑。下面我按照本文的叙述顺序说明常见的坑。
总结数据路由功能点很多,并且功能点之间存在优先级问题,会让路由变得复杂。考虑性能和高可用因素,OBProxy 路由功能还有一些可以完善的地方,如 增强 Parser 能力、支持多分区键路由计算、提高缓存实效性等。我们也在不断提高路由能力,解决大家的问题。 课后互动上期互动答案问:JDBC和OBProxy建立了一个连接,晚上OBProxy被kill掉重启,请问此时JDBC会抛出异常吗? 答:不会的。因为JDBC不感知 tcp 异常,所以只有在真正使用连接时才会发现连接出现问题,这种问题就会比较难排查。大家可以看JDBC的异常日志会打印上次发给 Server 的请求时间和上次从Server接收到请求的时间,如果接收请求的时间大于发送请求时间,那么上次请求应该是正常完成,可能就是上来就拿到了一个坏连接。 本期互动问题问:对于一个有表名的强读请求,如果SQL长度为7K,那么可能会如何路由? 欢迎你在问答区发帖讨论,下篇文章揭晓答案。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 5:07:18- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |