OceanBase 在 CPU、内存和 IO 隔离方面的详细实现机制:
CPU 隔离
基于线程数的隔离:
OceanBase 通过控制租户工作线程的数量来限制 CPU 使用。每个租户的 Unit 配置了
MAX_CPU参数,系统会根据该参数限制活跃线程数。 在 SQL 执行过程中,可能会有 IO 等待或锁等待,因此一个线程无法用满一个物理 CPU。默认情况下,每个 CPU 会启动 4 个线程,这个倍数可以通过配置项
cpu_quota_concurrency控制。 例如,如果一个 Unit 的
MAX_CPU是 10,那么它能同时运行的活跃线程是 40,最大物理 CPU 的占用是 400%。
基于 cgroup 的隔离:
从 V4.0.0 版本开始,OceanBase 支持使用 cgroup(Control Groups)对 CPU 进行强隔离
。cgroup 是 Linux 内核提供的机制,可以将不同租户的工作线程分配到不同的 cgroup 目录中,严格限制每个租户的 CPU 使用率 。 开启 cgroup 后,不同租户的工作线程会被放入不同的 cgroup 目录内,从而实现租户间的 CPU 强隔离
。 如果一个 OBServer 上只有一个租户负载很高,其余租户比较空闲,那么负载高的租户的 CPU 使用也会受到
MAX_CPU的限制。 如果有多个租户同时负载上升,导致物理 CPU 不够用,cgroup 会按照权重分配时间片
。
后台线程的隔离:
在 V4.0.0 版本中,后台线程也进行了租户拆分,每个租户下有对应的线程数控制
。 后台线程也会被放入不同的 cgroup 目录内,实现租户间隔离,以及租户内与工作线程的隔离
。
大查询处理:
OceanBase 认为短查询的快速返回对用户更有意义,因此大查询的优先级较低
。 当一个线程执行的 SQL 查询耗时过长,会被判定为大查询,执行大查询的线程会等待在一个 Pthread Condition 上,为其他租户的工作线程让出 CPU
。 大查询最多占用 30% 的租户工作线程,这个比例可以通过配置项
large_query_worker_percentage设置。
内存隔离
租户独立内存空间:
每个租户的内存资源是独立的,包括 SQL 执行过程中各种算子使用的内存、Block Cache 和 MemTable
。一个租户的内存耗尽不会影响其他租户的写入和读取 。 SQL 的 Plan Cache 和 Audit 表也是按租户分离的
。
资源单位(Unit)管理:
内存资源通过 Unit 进行分配和管理,每个 Unit 配置了
MEMORY_SIZE参数。 节点在启动时会探测物理机或容器的内存,并通过配置项
memory_limit或memory_limit_percentage来确定 Observer 进程可用的总内存。 Observer 进程的可用内存需要进一步扣除掉内部共用模块占用的内存,这部分内存大小由配置项
system_memory指定。
内存分配与监控:
OceanBase 支持通过
oceanbase.GV$OB_SERVERS视图查看每个节点的可用资源,包括内存容量和分配情况。
IO 隔离
基于 IOPS 参数的隔离:
OceanBase 使用
MIN_IOPS、MAX_IOPS和IOPS_WEIGHT参数来描述和管理磁盘带宽。 租户间的 IO 隔离是通过配置 Unit 来实现的。用户可以通过
UNIT CONFIG设定租户的 IOPS 参数,从而实现不同租户之间的 IO 隔离。 例如,创建一个 Unit 配置时,可以指定
MIN_IOPS=2000、MAX_IOPS=5000和IOPS_WEIGHT=1000。
租户内 IO 类别隔离:
租户内部的 IO 隔离是通过设置租户级配置项
io_category_config来实现的。 支持的 IO 类别包括
log、user、sys、prewarm和large_query。 可以通过配置项限制某一类别 IO 的最小、最大带宽和权重。例如,限制大查询类型的 IO 最大带宽不超过租户最大带宽的 60%,最小带宽不小于租户最小带宽的 30%
。
异步 IO 和 Direct IO:
OceanBase 使用异步 IO 和绕过操作系统的 Direct IO 来提高性能
。 IO 隔离通过控制提交异步 IO 的时间间隔来实现
。
通过上述机制,OceanBase 在多租户环境下实现了 CPU、内存和 IO 的高效隔离,确保不同租户之间互不干扰,同时提供了灵活的资源管理能力。




