【CSDN 编者按】10 月 2 日,国际事务处理性能委员会公布了数据库最新性能测试结果,在 TPC-C 基准测试中,由阿里巴巴集团蚂蚁金服自主研发的分布式关系数据库 OceanBase 打破了由 Oracle 保持了 9 年的 TPC-C 基准性能测试世界纪录,不仅成为首个登榜的中国数据库,更一举拿下世界第一,对此,中国工程院院士、计算机专家李国杰评价道:「这是中国基础软件取得的重大突破!」

本文作者 CSDN 博客专家马超对 OceanBase 的物理架构、数据及控制流程进行了分析,并解读开源部分的源码来剖析 OceanBase 是如何勇夺 TPC-C 冠军的。

作者 | 马超,CSDN 博客专家

责编 | 唐小引

出品 | CSDN 博客

封图 | CSDN 付费下载自东方 IC

我国高科技基础平台又有重大突破,继阿里和腾讯以及众多国内老牌嵌入式厂商相继宣传

不过经笔者刚刚多次尝试,目前 TPC 的官网(www.tpc.org)并无法在国内访问,所以全部的信息只能出自这个截图,我们可以看到如下两个信息,一是这个排行榜是以 tpmC 为基准进行排名的,这里解释一下 tpmC 其实是 TPC-C 三标准的一种度量方式,tpmC 中的 tpm 是 transactions per minute 的简写,即每分钟的交易量,C 代表 C 基准程序。它的定义是每分钟内系统处理的新订单个数。在这方面阿里的 OceanBase 的确是遥遥领先。

TPC-C 还经常以系统性能价格比的方式体现,单位是$/tpmC,即以系统的总价格(单位是美元)/tpmC 数值得出。这个笔者也已经在上图中标红,可见这个参数按现行汇率来说阿里的优势不明显。而且考虑到甲骨文的测试提交时间是 2011 年,而阿里的测试时间则是今年的 10 月 2 日。因此由于笔者也没拿到测试报告的原文,所以甲骨文是否还是以 11 年的硬件价格来做为分母计算性价比指标也尚不得而知。

因而综上所述,阿里在性能指标上的确是做到了遥遥领先,但是可能在硬件价格以及测试时间的方面占了一些先机。

OceanBase 在哪些方面做对了?

根据 OceanBase 的官网[1]介绍,其总体物理架构如下:

同时,从官网信息我们可以看到,OceanBase 在金融行业的应用案例为南京银行,因此笔者第一时间翻了一下南京银行朋友的票圈,了解了一下相关信息,目前南京分行在 OceanBase 上线的系统以互联网应用为主,而且根据其分享 OceanBase 在 Github 对自己的 0.4 版本进行了开源[2],目前虽然版本有更新,但是其基础设计没有根本改变,根据 GitHub 上的资源显示,其数据及控制流程总体如下:

OceanBase 将表的数据动态切分为 tablet,tablet 的数据分为动态和静态两部分。静态的数据存放在 chunkserver 上,所有对数据的修改都存储在 updateserver 中。updateserver 的修改定期同步到 chunkserver,chunkserver 将 updateserver 的更新和本地的静态数据合并,生成合并后的新数据。

tablet 的信息由 rootserver 维护,客户端在初始化时会请求 rootserver,获取 updateserver 的地址信息。客户端的更新请求(包括新增、修改和删除)都直接访问 updateserver。查询请求时客户端根据相应的 rowkey 向 rootserver 查询其对应的 tablet 信息,rootserver 返回相应的 mergeserver 地址,客户端根据返回的信息请求相应的 mergeserver 获取数据。

Mergeserver 收到请求时,根据 rowkey 从 rootserver 获取相应的 tablet 信息,该信息中包括负责该 tablet 的 chunkserver 列表,mergeserver 请求相应的 chunkserver,获取静态数据(如果有的话),然后根据返回的数据,请求 updateserver 获取相应的更新数据,将更新数据和静态的数据合并,将合并后的结果返回给客户端。

为了提高读取的性能,chunkserver 对部分数据结构进行了缓存。一个 SSTable 由多个 block 组成,为了加快定位需要请求的数据位于 SSTable 的哪个 block 中,chunkserver 包含一个 block index 的功能,block index 由该 block 负责的数据的最后一个 key 和该 block 在 SSTable 文件中的位置组成。为了提高 block 的读取性能,chunkserver 还将 block 缓存在内存中。Block index 和 block 的 cache 都采用 LRU 的策略淘汰。

笔者之前的博文中也介绍过,想提高效率必须做做减法,针对专门的场景做特定的优化。在笔者看到 OceanBase 的设计时,最令我印象深刻的是其 chunkserver 自带的缓存功能,而且根据之前的最佳实践分享,与甲骨文等传统数据库不同,OceanBase 与应用之间是不需要加 redius 缓存的,所以这点应该是阿里做的比传统数据库厂商厉害的地方。阿里的数据库之所以快基本上可以归功于这个 chunkserver 的功劳,下面我们就来进行一下代码解读。

速度秘诀:chunkserver 的设计与相关代码

其 chunkserver 的基础流程图如下:

可以看到负责数据查找和读取的部分是 SSTable 所以下面我们再对这部分做一下详细的代码解读,为便于查找,SSTable 会建立一些信息来索引数据,比如相关 key 在 SSTable 中的偏移,IndexBuilder 即用来建立这些信息。这部分的相关代码在:

https://github.com/alibaba/oceanbase/tree/master/oceanbase_0.4/src/sstable/ob_sstable_block_index_builder.cpp

其中重点函数是这个生成入口的函数 add_entry,这些都写得比较清楚,大家可以看一下。

int ObSSTableBlockIndexBuilder::add_entry(const uint64_t table_id,const uint64_t column_group_id,const ObRowkey &key, const int32_t record_size) {int ret     = OB_SUCCESS;ObSSTableBlockIndexItem index_item;//合法性校验if (record_size < 0 || key.get_obj_cnt() <= 0 || NULL == key.get_obj_ptr()|| table_id == OB_INVALID_ID || table_id == 0 || OB_INVALID_ID == column_group_id){TBSYS_LOG(WARN, "invalid param, table_id=%lu, key_len=%ld,""key_ptr=%p, record_size=%d, column_group_id=%lu", table_id, key.get_obj_cnt(), key.get_obj_ptr(), record_size, column_group_id);ret = OB_ERROR;}if (OB_SUCCESS == ret){//初始化,后面也是用以下的参数进行序列化的index_item.rowkey_column_count_ = static_cast<int16_t>(key.get_obj_cnt());index_item.column_group_id_ = static_cast<uint16_t>(column_group_id);index_item.table_id_ = static_cast<uint32_t>(table_id);index_item.block_record_size_ = record_size;index_item.block_end_key_size_ = static_cast<int16_t>(key.get_serialize_objs_size());index_item.reserved_ = 0; ret = index_items_buf_.add_index_item(index_item);if (OB_SUCCESS == ret) {ret = end_keys_buf_.add_key(key);if (OB_ERROR == ret){TBSYS_LOG(WARN, "failed to add end key");}else{index_block_header_.sstable_block_count_++;}}else{TBSYS_LOG(WARN, "failed to add index item");ret = OB_ERROR;}}return ret;}

和这个函数生成 index 的函数:

int ObSSTableBlockIndexBuilder::build_block_index(const bool use_binary_rowkey, char* index_block, const int64_t buffer_size, int64_t& index_size){int ret                   = OB_SUCCESS;int64_t index_block_size  = get_index_block_size();int64_t index_items_size  = get_index_items_size();int64_t header_size       = index_block_header_.get_serialize_size();int64_t pos               = 0;if (NULL == index_block){TBSYS_LOG(WARN, "invalid param, index_block=%p", index_block); ret = OB_ERROR;}else if (index_block_size == header_size){//no data in index blockret = OB_ERROR;}if (OB_SUCCESS == ret){index_block_header_.end_key_char_stream_offset_ = static_cast<int32_t>(header_size + index_items_size);// new rowkey obj array format, force set to 1.index_block_header_.rowkey_flag_ = use_binary_rowkey ? 0 : 1;if (OB_SUCCESS == index_block_header_.serialize(index_block,header_size, pos)){char* ptr = index_block + pos;ret = index_items_buf_.get_data(ptr, buffer_size - header_size);if (OB_SUCCESS == ret){ptr += index_items_size;ret = end_keys_buf_.get_data(ptr, buffer_size - header_size - index_items_size);if (OB_SUCCESS == ret){index_size = index_block_size;}}}else{TBSYS_LOG(WARN, "failed to serialize index block header");ret = OB_ERROR;}}return ret;}

并且,除了索引以外,OceanBase 还在读取之前添加了一个布隆过滤器,这个设计也比较有意思,Bloom Filter(布隆过滤器)用来判定某一个 key 是否属于某个集合,它有一定误判概率。如果判定在集合内,不一定在;但是如果判定不在集合内,那么一定不在,这样的操作可以优化很多 not in 的查询时间。这部分的代码在:

https://github.com/alibaba/oceanbase/tree/master/oceanbase_0.4/src/common/bloom_filter.h

https://github.com/alibaba/oceanbase/tree/master/oceanbase_0.4/src/common/bloom_filter.cpp

这里就不再贴代码了,大家有兴趣可以去上面的链接读一下相关代码。

后记

随着美国在高科技领域的不断施压,反而倒逼我国之前相对冷清的操作系统、数据库等基础平台领域重新热闹起来,笔者这个 C 语言的 IT 老兵感觉目前又焕发第二春,所以笔者还会继续关注相关领域的进展,后续继续带来代码级的解读,欢迎持续关注。

[1] https://oceanbase.alipay.com/product/oceanbase

[2] https://github.com/alibaba/oceanbase

扫描下方二维码,下载 CSDN App,与博主互动起来!

【END】

学Python 没找对路到底有多惨?

https://edu.csdn.net/topic/python115?utm_source=csdn_bw

 热 文 推 荐 

点击阅读原文,即刻与博主互动起来。

你点的每个“在看”,我都认真当成了喜欢

200 行代码解读国产数据库阿里 OceanBase 的速度源头!| CSDN 博文精选相关推荐

  1. 200行代码解读TDEngine背后的定时器

    作者 | beyondma来源 | CSDN博客 导读:最近几周,本文作者几篇有关陶建辉老师最新的创业项目-TdEngine代码解读文章出人意料地引起了巨大的反响,原以为C语言已经是昨日黄花,不过从读 ...

  2. 百度现场面试:JVM+算法+Redis+数据库!(三面)| CSDN博文精选

    戳蓝字"CSDN云计算"关注我们哦! 作者 |  中琦2513 转自 | CSDN博客 责编 | 阿秃 百度一面(现场) 自我介绍 Java中的多态 为什么要同时重写hashcod ...

  3. 宁愿“大小周”、每天只写 200 行代码、月薪 8k-17k 人群再涨!揭晓中国开发者真实现状...

    作者 | 郑丽媛 出品 | CSDN(ID:CSDNnews) 程序员,一个圈外人羡慕.圈内人喊苦的"神奇"职业--高薪.福利好是旁人羡慕的理由,高压.加班多却也是他们最常见的写照 ...

  4. 宁愿“大小周”、每天只写 200 行代码、月薪 8k-17k 人群再涨 | 揭晓中国开发者真实现状

    作者 | 郑丽媛 出品 | CSDN(ID:CSDNnews) 程序员,一个圈外人羡慕.圈内人喊苦的"神奇"职业--高薪.福利好是旁人羡慕的理由,高压.加班多却也是他们最常见的写照 ...

  5. js websocket同步等待_WebSocket硬核入门:200行代码,教你徒手撸一个WebSocket服务器...

    本文原题"Node.js - 200 多行代码实现 Websocket 协议",为了提升内容品质,有较大修订. 1.引言 最近正在研究 WebSocket 相关的知识,想着如何能自 ...

  6. blockchain 区块链200行代码:在JavaScript实现的一个简单的例子

    blockchain 区块链200行代码:在JavaScript实现的一个简单的例子 了解blockchain的概念很简单(区块链,交易链块):它是分布式的(即不是放置在同一台机器上,不同的网络设备上 ...

  7. JavaScript开发区块链只需200行代码

    JavaScript开发区块链只需200行代码 用JavaScript开发实现一个简单区块链.通过这一开发过程,你将理解区块链技术是什么:区块链就是一个分布式数据库,存储结构是一个不断增长的链表,链表 ...

  8. SpringBoot,用200行代码完成一个一二级分布式缓存

    缓存系统的用来代替直接访问数据库,用来提升系统性能,减小数据库复杂.早期缓存跟系统在一个虚拟机里,这样内存访问,速度最快. 后来应用系统水平扩展,缓存作为一个独立系统存在,如redis,但是每次从缓存 ...

  9. 爬虫python代码-Python爬虫教程:200行代码实现一个滑动验证码

    Python爬虫教程:教你用200行代码实现一个滑动验证码 做网络爬虫的同学肯定见过各种各样的验证码,比较高级的有滑动.点选等样式,看起来好像挺复杂的,但实际上它们的核心原理还是还是很清晰的,本文章大 ...

最新文章

  1. QS世界大学最新排名公布:清华超过耶鲁,MIT仍居榜首,12所中国高校跻身百强...
  2. ubuntu16.04装机:网易云+搜狗拼音+chrome+uGet+caffe(openCV3.1+CUDA+cuDNN+python)
  3. [reference]-ARM缩写
  4. 一天搞定CSS: overflow--14
  5. SQL语言之DQL语言学习(十)子查询
  6. 动态规划-重叠区间2020.3.30
  7. java 类加载器 解密_JAVA类加载器总结整理
  8. Java多线程知识小抄集(二)
  9. SAP UI5 初学者教程之二十七 - SAP UI5 应用的单元测试工具 QUnit 介绍试读版
  10. java第九章编写一个能够产生_第九章java教程.ppt
  11. java 中sub,Fn :: Sub中的嵌套Fn :: ImportValue不适用于SAM模板
  12. Tomcat 5 5-Manager App HOW-TO 翻译了部份 努力中
  13. 3个阶段 项目征名_项目管理的3个关键动作:启动、推进、复盘
  14. python解析库详解_PyQuery库详解
  15. python如何提取数据_python提取数据的常用方法
  16. 阿里矢量图可根据样式修改颜色
  17. 中文维基百科语料库 训练好的Word2vec模型
  18. 1. 神禹(shenyu)网关启动踩坑
  19. android l usb调试,你居然还不会手机usb调试?5个方法,让你轻松学会设置!
  20. java8-stream新特性详解及实战

热门文章

  1. 游戏中用户升级的设计
  2. ToString yyyy-MM-dd ,MM 小写的故事。
  3. 前端开发~uni-app ·[项目-仿糗事百科] 学习笔记 ·006【底部导航开发】
  4. mysql 设置男女约束
  5. 剑指offer之把二叉树打印成多行
  6. 剑指Offer之数组中重复的数字
  7. TypeScript报错--找不到模块“path”或其相应的类型声明
  8. Flutter实战一Flutter聊天应用(十五)
  9. 塑料浮船坞行业调研报告 - 市场现状分析与发展前景预测
  10. 2021年中国窗口句柄市场趋势报告、技术动态创新及2027年市场预测