当前位置: 首页 > java >正文

OceanBase架构设计

本文主要参考《大规模分布式存储系统》

基本结构

客户端:发起请求。

RootServer:管理集群中的所有服务器,子表数据分布及副本管理,一般为一主一备,数据强同步。

UpdateServer:存储增量变更数据,一般为一主一备,客户端的写入数据只更UpdateServer。

MergeServer:接收并解析SQL请求,进行词法分析和查询优化之后把请求转发给ChunkServer查询,并合并查询后的结果。客户端直接访问MergeServer。

ChunkServer:存储基线数据,一般存储两到三份。

上述组件可以构成一个OB集群,另外还可以在此基础上部署多个集群,集群之间的数据同步通过主集群的UpdateServer向备集群同步来实现。

组件实现

RootServer

RootServer负责管理集群中所有的MergeServer,ChunkServer和UpdateServer,功能主要包括以下三点:

集群管理

RootServer通过心跳与其他组件连接。

保证一个集群内同一时刻只有一个UpdateServer提供服务,通过租约机制选择唯一的主UpdateServer。

数据分布
中心表RootTable

使用主键对表格数据排序,按顺序分布(和Hbase一样)。把所有数据划分为大致相等的数据范围(Tablet),每个子表默认256MB。采用根表一级索引结构,即只有根表和子表两层。

由于中心表RootTable的修改很少,直接使用有序数组实现,增加子表时通过CopyOnWrite的方式创建一个新的数据,对新的数据写入和重新排序,然后吧指针指向新的RootTable。

子表分裂和合并

分裂:每台ChunkServer采用同样的分裂规则,根据子表的数据行数和子表大小设定分裂规则。

合并:先选择若干连续范围的子表,把它们迁移到相同的ChunkServer机器上,然后执行合并。只要有一个副本合并成功,就认为合并成功。

副本管理

每个子表一般包含3个副本,RootServer定期执行负载均衡,转移子表到负载低的节点。

RootServer的主备之间数据强一致同步。

UpdateServer

集群中只有UpdateServer接收写操作,更新时首先写入内存,当内存表的数据量超过阈值时转储到磁盘。和Hbase一样,为了保证可靠性,写入数据前先写入操作日志并同步到备UpdateServer。

由于只有一台UpdateServer提供写服务,很容易实现跨行跨表事务。

UpdateServer中的增量数据结构为一颗内存中的B+树(Hbase为跳跃表),每个叶子结点对应一行数据,key为行主键,value为行操作链表的指针,每行按照时间顺序构成一个行操作链表(更新、删除)。

UpdateServer的主备节点各保存增量数据的一个副本,以此保证高可用。同步机制跟MySQL的主备同步一致基本一样,主UpdateServer往备机推送操作日志,备UpdateServer接受线程接收日志并写入全局日志缓冲区。

ChunkServer

ChunkServer是集群中实际存储数据的节点,数据结构为B+树。每个表格按主键组成一颗B+树,每个叶子结点包含表格中某个主键范围内的数据。每个叶子结点称为一个子表(Tablet),包含一个或多个SSTable,每个SSTable由多个块组成,支持布隆过滤器过滤。叶子结点是负载平衡和任务调度的基本单元。

ChunkServer中保存基线数据的2-3个副本,以此保证高可用

ChunkServer的功能主要包括以下:

存储多个子表

每个子表由1个SSTable组成,每个SSTable由多个块组成,每个块大小为4KB-64KB之间(和HBase一样)。

支持两种缓存:块缓存和行缓存。

SSTable分为两种格式:稀疏格式和稠密格式。稀疏格式的每一行只存储包含实际值的列(列存储),稠密格式每一行需要存储所有列,但不需要存储列名(行存储)。

列存储的好处有两个:

  1. 在SQL语句只读取部分列时,避免把完整行加载到内存中。
  2. 同一列数据在物理上存放到一起,提高压缩率。
提供读取服务

MergeServer把请求发到子表所在的ChunkServer读取基线数据,然后请求UpdateServer获取增量数据并融合。

定期合并

把UpdateServer转储来的增量表和本地的基线数据执行多路合并,生成新的SSTable。

数据分发

冻结UpdateServer当前活跃的内存表,生成冻结内存表并缓存到ChunkServer中。

MergeServer

负责解析用户的SQL请求、转发到ChunkServer执行、合并结果并返回。

MergeServer中缓存子表信息以减少对RootServer的读取。MergeServer本身是无状态的,理论上在宕机后不会对使用者产生影响。

SQL执行

读取

select c1, sum(c2)
from t1
where c3=10
group by c1
having sum(c2) >= 10
order by c1
limit 0, 20

执行顺序依次为:

TableScan(table = t1, col = {c1, c2, c3}, filter = {c3 = 10}):读取数据。

HashGroupBy(groupby = {c1}, aggr = {sum)(c2)}):分组并计算每个分组内c2的总和。

Filter(cond = {sum(c2) >= 10}):过滤。

Sort(col={c1}):排序。

Project(col = {c1, sum(c2}):返回指定列。

Limit(offset = 0, count = 20):返回限定行数。

select t1.c1, sum(t2.c3)
from t1, t2
where t1.c2 = t2.c2and t1.c3=10
group by t1.c1
having sum(t2.c3) >= 10
order by t1.c1
limit 0, 20

执行顺序依次为:

TableScan(table = t1, col = {c1, c2, c3}, filter = {c3 = 10}) 和 TableScan(table = t2, col = {c1, c2, c3}, filter = {c3 = 10}) 分别读取数据。

Sort(col={t1.c2) 和 Sort(col={t2.c2) 分别排序。

MergeJoin(cond = {t1.c2 = t2.c2}) 合并两张表的结果。

… 后面和单表一样。

写入

REPLACE:直接写入UpdateServer。

INSERT:读取ChunkServer中的基线数据并发送到UpdateServer,如果行已存在则返回错误,不存在则执行插入操作。

UPDATE:如果行已存在则执行更新,否则什么也不做。

DELETE:如果行已存在则执行删除,否则什么也不做。

多版本并发控制

写操作的两个步骤:

预提交:锁住待更新行,把操作追加到该行的未提交行操作链表中,然后往提交任务队列加入一个提交任务。

提交:线程从提交任务队列中获取提交任务,然后把任务的操作日志写入到日志缓冲区中(缓冲区满时写入磁盘)。操作日志写成功后,把未提交行操作链表追加到已提交行操作链表,释放锁。

默认情况的隔离级别为读已提交。

单行只写事务预提交时对单行加写锁;多行只写事务预提交时对所有行加写锁;读写事务中的读操作是读取某个版本的快照。

允许用户显式锁住某一行(select xxx for update),发生死锁时超过指定时间自动回滚。

一些设计

  1. 惊群效应:N个线程同时读取一行已失效的缓存,第一个线程在读取时往缓存中加入fake标记,其他线程发现fake标记时先等待。
  2. LightyQueue:使用多个队列分散读写请求。
  3. 双缓存机制:分配当前和预读两个缓冲区,使用当前缓冲区读取完成并返回上层计算之后,预读缓冲区切换成当前缓冲区并异步读取数据,原来的当前缓存区计算完之后清空内存并切换成预读。
http://www.xdnf.cn/news/17464.html

相关文章:

  • 後端開發技術教學(四) 數據交互延伸
  • 如何更改win11自带录音机所录制文件的存储路径
  • 新手入门:从零开始使用这份 LaTeX 模板
  • nishang--安装、使用
  • Java Stream 使用 Fork/Join框架的分治任务模型
  • 计算机视觉CS231n学习(6)
  • 基于遗传优化的稀疏线阵最优排布算法matlab仿真
  • day30-HTTP
  • 嵌入式C语言高效操作寄存器指南
  • Jenkins全链路教程——并行任务与超时控制
  • 应急响应。
  • Swift 实战:秒算两个数组的交集(LeetCode 349)
  • 快手短剧用户破新高, 累计付费用户数同比提升4倍
  • 【linux基础】Linux 文本处理核心命令指南
  • 力扣 30 天 JavaScript 挑战 第二题笔记
  • 【RH134知识点问答题】第 3 章:分析和存储日志
  • 永磁同步电机无速度算法--零速启动非线性磁链观测器
  • QT第二讲-信号和槽
  • 企业WEB服务器nginx新手超详细讲解
  • 机器学习DBSCAN密度聚类
  • 【线程池】压测确定线程池合适的参数
  • 华为实验:DHCP 典型配置
  • 深入理解Qt事件处理机制
  • 新手向:Python开发简易待办事项应用
  • Linux 中CentOS Stream 8 - yum -y update 异常报错问题
  • [每周一更]-(第155期):深入Go反射机制:架构师视角下的动态力量与工程智慧
  • Spring Boot自定义Starter:从原理到实战全解析
  • GM3568JHF:FPGA+ARM异构开发板环境搭建教程
  • 免费PDF编辑软件 pdf24-creator 及其安装包
  • C语言(10)——结构体、联合体、枚举