OceanBase 源码解读(十五):Location Cache 模块浅析

2024年 5月 7日 120.4k 0

OceanBase 源码解读(十五):Location Cache 模块浅析-1

本文作者:镇楠,OceanBase 内核研发工程师,对于分布式集群中副本位置信息的管理方法有着丰富的理解。

此前,OceanBase 源码解读第十篇《一号表及其服务寻址》,为大家介绍了“系统租户的「一号表」”的前世今生,并对一号表相关的服务寻址过程进行了说明。本期“源码解读”继续由 OceanBase 内核研发工程师镇楠为大家带来文中提及的 Location Cache 模块浅析。

Location cache 是 observer 上的一个基础模块,为 SQL、事务、CLOG 等多个其他模块提供获取及缓存某个副本位置信息的能力。Location cache 依赖各级 meta 表以及底层 partition_service、log_service 的服务获取副本的位置信息,通过各模块的调用被动刷新及缓存 cache。同一个 observer 各模块共享同一个 Location cache。

OceanBase 源码解读(十五):Location Cache 模块浅析-1

一、location cache 的缓存内容

在 OceanBase 集群中,各个副本的位置信息记录在 meta table 中。如果每次访问副本,都要发 SQL 去 meta table 里面找一遍位置,未免效率太低。因此我们在每个 ObServer 中都会缓存实体表的位置信息,由 location cache 模块负责管理,在 ObPartitionLocationCache 中实现。其主要缓存内容如下:

1、核心 location cache

sys_cache_ 缓存系统表 location 信息,user_cache_ 缓存用户表 location 信息。

之所以采用不同数据结构分开存储,是为了避免用户表数量过大,将系统表的 location cache 挤掉。

OceanBase 源码解读(十五):Location Cache 模块浅析-3

2、leader cache

  • sys_leader_cache_:用来缓存本集群系统租户系统表的 leader 信息。

该 cache 的提出是为了在有限场景上支持不依赖内部表获取系统租户系统表 leader 的功能。一方面是为了解决分布式事务推进获取不到系统表 leader 死锁的问题,另一方面可稍微优化获取系统租户系统表 leader 的速度。

  • leader_cahce_ 用来缓存用户表的 leader 信息。

引入它是考虑到从 KVCache 的结构中获取 location 有一定消耗,又增加一层 leader_cache_ 来缓存 leader 位置信息,从而优化 nonblock_get_leader() 方法的 location 获取路径。

OceanBase 源码解读(十五):Location Cache 模块浅析-4

二、location cache 模块对外提供的能力

location cache 模块缓存以各个 observer 为主体,将访问过的实体表的位置信息缓存在本地。location cache 采用被动刷新机制,当其他内部模块发现cache失效时,需调用刷新接口刷新 cache。

对应缓存内容,location cache 模块对外提供获取具体 pkey(pgkey) 对应的 partition 和 leader 位置信息的能力。主要应用于 SQL、Proxy、storage、transaction、clog(后两者重点关注 leader 信息)等模块,接口如下所示:

//同步接口:
int ObPartitionLocationCache::get(const uint64_t table_id,
                                  const int64_t partition_id,
                                  ObPartitionLocation &location,
                                  const int64_t expire_renew_time,  //该参数为INT64_MAX时,表示强制刷新。bool &is_cache_hit,const bool auto_update /*= true*/) //get函数带有刷新功能
int ObPartitionLocationCache::get_strong_leader(const common::ObPartitionKey &partition,
                                                common::ObAddr &leader,
                                                const bool force_renew) //本质上通过get函数获取leader,也带刷新功能
//异步接口:
int ObPartitionLocationCache::nonblock_get(const uint64_t table_id,
                                           const int64_t partition_id,
                                           ObPartitionLocation &location,
                                           const int64_t cluster_id)  //以nonblock方式从location cache中查询
int ObPartitionLocationCache::nonblock_get_strong_leader(const ObPartitionKey &partition, ObAddr &leader) //优先从leader cache中查,没有则走nonblock_get
int ObPartitionLocationCache::nonblock_renew(const ObPartitionKey &partition,
                                             const int64_t expire_renew_time,    
                                             const int64_t specific_cluster_id) //配合上面两个函数,访问失败则刷新location cache。通过ObLocationAsyncUpdateTask实现

其中 nonblock_renew() 通过任务队列的方式实现。

OceanBase 源码解读(十五):Location Cache 模块浅析-5

OceanBase 源码解读(十五):Location Cache 模块浅析-6

其中通过多个队列划分优先级,加快异常场景恢复速度:

  1. pall_root_update_queue_; // __all_core_table、__all_root_table、__all_tenant_gts、__all_gts
  2. prs_restart_queue_; // rs restart related sys table
  3. psys_update_queue_; // other sys table in sys tenant
  4. puser_ha_update_queue_; // __all_dummy、__all_tenant_meta_table
  5. ptenant_space_update_queue_; // sys table in tenant space
  6. puser_update_queue_; // user table

三、location cache 的刷新机制

主要刷新流程:

OceanBase 源码解读(十五):Location Cache 模块浅析-7

1、SQL 刷新——最初的刷新方式

SQL 刷新顾名思义,就是通过 SQL 语句去 meta table 中查询 location 信息来刷新本地 cache。该刷新过程与汇报过程如出一辙。

OceanBase 源码解读(十五):Location Cache 模块浅析-8

SQL 刷新依赖与 meta table 可读以及汇报流程运行正常。SQL 刷新存在一定延时,例如,在 leader 变更,汇报正在进行的时候进行 SQL 刷新,返回的是仍是旧的 leader。该问题通过再次刷新即可解决。

2、RPC 刷新——不依赖 meta table 的刷新方式

为什么提出 RPC 刷新?

因为 SQL 刷新依赖 meta 表、SQL 模块、底层汇报,在网络异常的情况下,会导致location cache一直无法刷新。比如下图中,meta 表所在的 server A 与 DEF 网络断连,D 发出刷新请求,此时无法 SQL 刷新,但可以通过 EF 上同一 partition 的副本 location 信息确定 D 的 location。一定程度上减少对于 meta table 的依赖,减少 SQL 查询消耗,加速 cache 刷新。

OceanBase 源码解读(十五):Location Cache 模块浅析-9

RPC 刷新的实现

中心思想:通过旧 cache 拿到本 region 的 partition 的所有副本位置信息,RPC 到对应的 server 上通过 partition service 获取 member_info(含leader、member_list、lower_list等),通过对比 member_info 和旧的 location 信息,感知 leader 和 replica type 的变化(F->L)。

成功刷新的条件:member_list 未改变,non_paxos 成员未改变。

RPC 刷新的优缺点:

优点:消耗很小,能更快速地感知到 leader 和成员列表中副本变更,针对无主选举、leader 改选等场景有较好的效果。所以我们会优先使用 RPC 刷新。

缺点:RPC 刷新实现为了尽可能高效,仅保证该副本的 leader、paxos 成员列表、直接级联在本 region paxos 成员下只读副本的 location 信息是准确的,无法感知到二级及以上级联的只读副本的变更,也无法感知级联在其他 region 下的只读副本变更。

3、其他机制

强制 SQL 刷新

  1. 目的:RPC 刷新无法感知到异地只读副本变化、二级及以上的级联只读副本变化;
  2. 方法:

     定时 SQL 刷新,FORCE_REFRESH_LOCATION_CACHE_INTERVAL

     限制每秒SQL刷新次数,FORCE_REFRESH_LOCATION_CACHE_THRESHOLD

批量刷新

  1. 目的:优化 RTO 场景 location cache 刷新速度,对日常 SQL 执行也有优化效果;
  2. 方法:

按 partition table 类型分类任务

按 Sys partitions 和 user partitions分类

按租户分类

__all_core_table/__all_root_table 的 location_cache 单独刷新

四、虚表的 location cache

虚表没有存储实体,在查询的时候才会按照特定规则生成。为了统一 SQL 层的查询逻辑,Location cache 模块为虚表的查询提供了特殊的“位置信息”。

1、虚表的分类

从分布情况的角度,虚表可以分为以下三类:

  1. LOC_DIST_MODE_ONLY_LOCAL:只在本地执行的虚表
  2. LOC_DIST_MODE_DISTRIBUTED:分布式执行的虚表(包括集群级和租户级)
  3. LOC_DIST_MODE_ONLY_RS:需要 RS 上才能执行的虚表

2、虚表获取 location

//关键函数:
int ObSqlPartitionLocationCache::virtual_get(const uint64_t table_id,const int64_t partition_id,share::ObPartitionLocation &location,const int64_t expire_renew_time,bool &is_cache_hit)

//LOC_DIST_MODE_ONLY_LOCAL://只需要自身的地址
int ObSqlPartitionLocationCache::build_local_location(uint64_t table_id,ObPartitionLocation &location)
|-replica_location.server_ = self_addr_; 

//LOC_DIST_MODE_DISTRIBUTED://本质上就是集群的server_list
int ObSqlPartitionLocationCache::build_distribute_location(uint64_t table_id, const int64_t partition_id,ObPartitionLocation &location)
|-int ObTaskExecutorCtx::get_addr_by_virtual_partition_id(int64_t partition_id, ObAddr &addr)

//LOC_DIST_MODE_ONLY_RS://本质上就是RS的位置
int ObSqlPartitionLocationCache::get(const uint64_t table_id,ObIArray<ObPartitionLocation> &locations,const int64_t expire_renew_time,bool &is_cache_hit,const bool auto_update /*=true*/)
|-int ObPartitionLocationCache::get(const uint64_t table_id,ObIArray<ObPartitionLocation> &locations,const int64_t expire_renew_time,bool &is_cache_hit,const bool auto_update /*=true*/)
| |-int ObPartitionLocationCache::vtable_get(const uint64_t table_id,ObIArray<ObPartitionLocation> &locations,const int64_t expire_renew_time,bool &is_cache_hit)
| | |- int renew_vtable_location(const uint64_t table_id,common::ObSArray<ObPartitionLocation> &locations);

言而总之,我们将虚表的 location cache 概括成三句话:

  1. 对于本地执行的虚表,Location cache 模块返回本地 server 的地址;
  2. 对于分布式执行的虚表,Location cache 模块返回集群的 server_list;
  3. 对于 RS 执行的虚表,Location cache 模块返回 RS 所在 server 的地址。

————————————————

(未完待续)

附录:前十四篇可参考:

1、OceanBase 数据库源码解读(一)引言

2、OceanBase 数据库源码解读(二)目录结构

3、OceanBase 源码解读(三)SQL 的一生

4、OceanBase 源码解读(四)分区的一生

5、OceanBase 源码解读(五)事务的一生

6、OceanBase 源码解读(六)租户的一生

7、OceanBase源码解读(七)带你看透虚拟表

8、OceanBase源码解读(八)OceanBase 高性能执行引擎

9、OceanBase源码解读(九)TableAPI 和 OceanBase 多模型

10、OceanBase 源码解读(十)分布式事务

11、OceanBase 源码解读(十一):表达式和函数

12、OceanBase 源码解读(十二):事务日志的提交和回放

13、OceanBase 源码解读(十三):一号表

14、OceanBase 源码解读(十四):集群位置信息的存储与汇报

最后的最后,您有任何疑问都可以通过以下方式联系到我们~

联系我们

欢迎广大 OceanBase 爱好者、用户和客户随时与我们联系、反馈,方式如下:

社区版官网论坛

社区版项目网站提 Issue

钉钉群:33254054

OceanBase 源码解读(十五):Location Cache 模块浅析-10

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论