UpdateServer存储引擎如下图所示。

UpdateServer存储引擎与Bigtable存储引擎看起来很相似,不同点在于:

  • UpdateServer只存储了增量修改数据,基线数据以SSTable的形式存储在Chunkserver上,而Bigtable存储引擎同时包含某个子表的基线数据和增量数据;
  • UpdateServer内部所有表格共用MemTable以及SSTable,而Bigtable中每个子表的MemTable和SSTable分开存放;
  • Updateserver的SSTable存储在SSD磁盘中,而Bigtable的 SSTable存储在GFS中。

UpdateServer存储引擎包含几个部分:操作日志、MemTable以及ssTable。更新操作首先记录到操作日志中,接着更新内存中活跃的MemTable(Active MemTable)活跃的MemTable到达一定大小后将被冻结,称为Frozen MemTable,同时创建新的Active MemTables Frozen MemTable将以SSTable文件的形式转储到SSD磁盘中。

1.操作日志

OceanBase中有一个专门的提交线程负责确定多个写事务的顺序(即事务id),将这些写事务的操作追加到日志缓冲区,并将日志缓冲区的内容写人日志文件。为了防止写操作日志污染操作系统的缓存,写操作日志文件采用Direct IO的方式实现:

class ObLogWriter
{
public://write_1og高数清操作日志存入日志统冲区int write_log(const LogComand cmd, const char* log_data, const int64_t data_len);//将日志缓冲区中的日志先同步到备机再写入主机磁盘int flush_log(LogBuffer&  tlog_buffer, const bool sync_to_slave = true, const bool is_master = true);

每条日志项由四部分组成:日志头+日志序号+日志类型(LogCommand)+日志内容,其中,日志头中记录了每条日志的校验和(checksum)。ObLogWriter中的write_log函数负责将操作日志拷贝到日志缓冲区中,如果日志缓冲区已满,则向调用者返回缓冲区不足(OB_BUF_NOT_ENOUGH)错误码。接着,调用者会通过flush_log将缓冲区中已有的日志内容同步到备机并写入主机磁盘。如果主机磁盘的最后一个日志文件超过指定大小(默认为64MB),还会调用switch_log函数切换日志文件。为了提高写性能,UpdateServer实现了成组提交(Group Commit)技术,即首先多次调用write_log函数将多个写操作的日志拷贝到相同的日志缓冲区,接着再调用flush_log函数将日志缓冲区中的内容一次性写入到日志文件中。

2.MemTable

MemTable底层是一个高性能内存B树。MemTable封装了B树,对外提供统一的读写接口。

B树中的每个叶子节点对应MemTable中的一行数据,key为行主键,value为行操作链表的指针。每行的操作按照时间顺序构成一个行操作链表。

如下图所示,MemTable的内存结构包含两部分:索引结构以及行操作链表,索引结构为B树,支持插入、删除、更新、随机读取以及范围查询操作。行操作链表保存的是对某一行各个列(每个行和列确定一个单元,称为Cell)的修改操作。

【例】对主键为1的商品有3个修改操作,分别是:将商品购买人数修改为100,删除该商品,将商品名称修改为“女鞋”,那么,该商品的行操作链中将保存三个Cell,分别为: <update,购买人数,100> 、<delete,*> 以及 <update,商品名,“女鞋”>

MemTable中存储的是对该商品的所有修改操作,而不是最终结果。另外,MemTable删除一行也只是往行操作链表的末尾加入一个逻辑删除标记,即 <delete,*> ,而不是实际删除索引结构或者行操作链表中的行内容。

MemTable实现时做了很多优化,包括:

  • 哈希索引:针对主要操作为随机读取的应用,MemTable不仅支持B树索引,还支持哈希索引,UpdateServer内部会保证两个索引之间的一致性。
  • 内存优化:行操作链表中每个cell操作都需要存储操作列的编号(column_id)、

操作类型(更新操作还是删除操作)、操作值以及指向下一个cell操作的指针,如果不做优化,内存膨胀会很大。为了减少内存占用,MemTable实现时会对整数值进行变长编码,并将多个cell操作编码后序列到同一块缓冲区中,共用一个指向下一批cell操作缓冲区的指针:

struct ObCellMeta
{const static int64_t TP_INT8 = 1; //int8整数类型const static int64_t TP_INT16 = 2; //int16整数类型const static int64_t TP_INT32 = 3; //int32整数类型const static int64_t TP_INT64 = 4; //int64整数类型const static int64_t TP_VARCHAR = 6; //变长字符串类型const static int64_t TP_DOUBLE = 13; //双精度浮点类型const static int64_t TP_ESCAPE = 0x1f; //扩展类型const static int64_t ES_DEL_ROW = 1; //删除行操作
};class ObCompactCellwriter
{public://写入更新操作,存储成压缩格式int append(uint64_t column_id, const ObObj& value);//写入删除操作,存储成压缩格式int row_delete();
};

MemTable通过ObCompactCellWriter来将cell操作序列化到内存缓冲区中,如果为更新操作,调用append函数;如果为删除操作,调用row_delete函数。更新操作的存储格式为:数据类型+值+列ID,TP_INT8/TP_INT16/TP_INT32/TP_INT64分别表示8位/16位/32位/64位整数类型,TP_VARCHAR表示变长字符串类型,TP_DOUBLE表示双精度浮点类型。删除操作为扩展操作,其存储格式为:TP_ESCAPE+ES_DEL_ROW。例9-3中的三个Cell;<update,购买人数,100>、<delete,*>以及<update, 商品名,“女鞋”> 在内存缓冲区的存储格式为:

1 2 3 4 5 6 7 8
TP_INT8 100 购买人数列ID TP_ESCAPE ES_DEL_ROW TP_VARCHAR 女鞋 商品名列ID

第1~3字节考示第一个Cell,即<update,购买人数,100> ;第4~5字节表示第二个cell,即<delete. *> ;第6~8字节表示第三个Cel1,即<update,商品名,“女鞋”>

MemTable的主要对外接口可以归结如下:

//开启一个事务
// @param [in] trans_type 事务类型,可能为读事务或者写事务
// @param [out] id 返回的事务描述符
int start_transaction(const TETransType trans_type, MemTableTransDescriptor& td);
// 提交或者回滚一个要新
// @param [in] td 事务描述符
// @param [in] rollback 是否回滚,默认为false
int and transation(conat MemTableTransDescriptor td, bool rollback = false);
// 执行随机读取操作,返回一个选代器
// @param [in] td 事务描述符
// @param [in] table_id 表格编号
// @param [in] row key 待查询的主键
// @param [out]iter 返回的迭代器
int get(const MemTableTransDescriptor td, const uint64_t table_id,const ObRowkey& row key, MemTableIterator& iter);
// 执行范围查询操作,返回一个选代器
// @param [in] td 事务描述符
// @param [in] range 查询范周,包括起始行、结束行,开区间或者闭区间
// @param [out] iter 返回的迭代器
int scan(const MemTableTransDescriptor td, const ObRange& range, MemTableIterator& iter);
// 开始执行一次修改操作
// @param [in] td 事务描述符
int atart_mutatlon(const MemTableTransDescriptor td);
// 提交或者回滚一次修改操作
// @param [in] td 事务描述符
// @param [in] rollback 是否回滚
int end _mutation(const MemTableTransDescriptor td, bool rollback);
//执行修改操作
// @param [in] td 事务描述符
// @param [in] mutator 修改操作,包含一个或者多个对多个表格的cell操作
int set(const MemTableTransDescriptor td, ObUpsMutator& mutator);

对于读事务,操作步骤如下:

  1. 调用start transaction开始一个读事务,获得事务描述符;
  2. 执行随机读取或者扫描操作,返回一个迭代器;接着可以从迭代器不断迭代数据;
  3. 调用end transaction提交或者回滚一个事务。
class MemTableIterator
{
public://迭代器移动到下一个cellint next cell();//获取当前cell的内容//@param [out] cell_info 当前cell的内容,包括表名(table_id),行主健(row_key),列编号(column_id)以及列值(column_value)int get_cell(obcellInfo** cell_info);//获取当前cell的内容//@param [out] cell_info 当前cell的内容//@param is_row_changed 是否迭代到下一行int get_cell(obcellInfo** cell_info, bool* is_row_changed);
};

读事务返回一个迭代器Mem Tablelterator,通过它可以不断地获取下一个读到的cell。在【例】中,读取编号为1的商品可以得到一个迭代器,从这个迭代器中可以读出行操作链中保存的3个Cell,依次为:<update,购买人数,100>,<delete, *>,<update, 商品名, “女鞋”>

写事务总是批量执行,步骤如下:

  1. 调用start transaction开始一批写事务,获得事务描述符;
  2. 调用start mutation开始一次写操作;
  3. 执行写操作,将数据写入到MemTable中;
  4. 调用end_mutation提交或者回滚一次写操作;如果还有写事务,转到步骤2;
  5. 调用end transaction提交写事务。

3.SSTable

当活跃的MemTable超过一定大小或者管理员主动发起冻结命令时,活跃的MemTable将被冻结,生成冻结的MemTable,并同时以SSTable的形式转储到SSD磁盘中。

SSTable的详细格式请参考ChunkServer实现机制,与ChunkServer中的SSTable不同的是,UpdateServer中所有的表格共用一个SSTable,且SSTable为稀疏格式,也就是说,每一行数据的每一列可能存在,也可能不存在修改操作。

另外,OceanBase设计时也尽量避免读取UpdateServer中的SSTable,只要内存足够,冻结的MemTable会保留在内存中,系统会尽快将冻结的数据通过定期合并或者数据分发的方式转移到ChunkServer中去,以后不再需要访问UpdateServer中的SSTable数据。

当然,如果内存不够需要丢弃冻结MemTable,大量请求只能读取SSD磁盘,UpdateServer性能将大幅下降。因此,希望能够在丢弃冻结MemTable之前将SSTable的缓存预热。

UpdateServer的缓存预热机制实现如下:在丢弃冻结MemTable之前的一段时间(比如10分钟),每隔一段时间(比如30秒),将一定比率(比如5%)的请求发给SSTable,而不是冻结MemTable。这样,SSTable上的读请求将从5%到10%,再到15%,依次类推,直到100%,很自然地实现了缓存预热。

分布式存储引擎OceanBase,UpdateServer 实现机制——存储引擎相关推荐

  1. mysql 储存引擎_详解mysql存储引擎的标准

    浅谈选择mysql存储引擎的标准 主要存储引擎的介绍 1.InnoDB存储引擎 InnoDB是MySQL的默认事务型引擎,它被设计用来处理大量的短期(short-lived)事务.除非有非常特别的原因 ...

  2. Mysql的数据库引擎 区别特点_mysql数据库存储引擎及区别

    MySQL有多种存储引擎,每种存储引擎有各自的优缺点,可以择优选择使用: MyISAM.InnoDB.MERGE.MEMORY(HEAP).BDB(BerkeleyDB).EXAMPLE.FEDERA ...

  3. MySQL技术内幕 InnoDB存储引擎——第2章 InnoDB存储引擎(未完待续)

    第2章 InnoDB存储引擎 2.1 InnoDB存储引擎概述 InnoDB存储引擎是第一个完整支持ACID事务的MySQL存储引擎(BDB是第一个支持事务的MySQL存储引擎,现在已经停止开发). ...

  4. mysql 存储引擎接口_MySQL体系结构和存储引擎

    数据库与传统文件系统最大的区别在于数据库是支持事务的 一.定义数据库与实例 1.数据库: 物理操作系统的文件或者其他文件类型的集合,依照某种数据模型组织起来并存储于二级存储器中的数据集合. 2.实例: ...

  5. MySQL存储引擎 lnnoDB逻辑架构 innodb存储引擎表空间(ibd文件)详解 回滚日志的物理空间

    文章目录 存储引擎 一 MySQL组织架构 二 查看存储引擎信息 三 修改存储引擎 3.1 配置文件修改存储引擎 3.2 临时修改存储引擎 3.3 建表时修改存储引擎 四 存储引擎实验 五 数据库升级 ...

  6. mysql and常用引擎_MySQL两大常用存储引擎MyISAM,InnoDB的区别

    本文主要整理了MySQL两大常用的存储引擎MyISAM,InnoDB的六大常见区别,来源于Mysql手册以及互联网的资料 InnoDB与Myisam的六大区别 MyISAM InnoDB 构 成上的区 ...

  7. mysql中最常用的存储引擎有_mysql常用的存储引擎有哪些

    MySql中的存储引擎有MyISAM引擎,MyISAM Merge引擎, InnoDB引擎,memory(heap)引擎以及archive引擎 MySql中的存储引擎 MyISAM引擎 这种引擎是my ...

  8. mysql改存储引擎教程_MySQL修改默认存储引擎

    mysql存储引擎: MySQL服务器采用了模块化风,各部分之间保持相对独立,尤其体现在存储架构上.存储引擎负责管理数据存储,以及MySQL的索引管理.通过定义的API,MySQL服务器能够与存储引擎 ...

  9. mysql数据库引擎简介_MySQL数据库的存储引擎简介

    存储引擎 MySQL中的数据用各种不同的技术存储在文件(或者内存)中.这些技术中的每一种技术都使用不同的存储机制.索引技巧.锁定水平并且最终提供广泛的不同的功能和能力.通过选择不同的技术,你能够获得额 ...

  10. mysql有那些存储引擎_MySQL有那哪些存储引擎

    实际我们在平时的开发中,经常会遇到的,在用SQLyog等工具创建表时,就有一个引擎项要你去选.如下图: Mysql的存储引擎有这么多种,实际我们在平时用的最多的莫过于InnoDB和MyISAM了. 所 ...

最新文章

  1. 后浪来袭!拼多多黄峥身价超过马云,成为中国第二大富豪
  2. 长沙理工大学计算机系教师,长沙理工大学数学与计算机科学学院导师介绍:王晚生...
  3. VB中Unicode vs Ansi-From alpsong(阿尔卑斯之歌)
  4. Trie 树是什么样的数据结构?有哪些应用场景?
  5. aws java mysql_java - AWS EC2 / MySql - spring boot无法从datasource确定jdbc url - 堆栈内存溢出...
  6. Redis 学习---(6)Redis 键(key)
  7. 新泽西州男子因无牌运营比特币交易所或面临5年监禁
  8. kademlia(卡德米利亚)算法原理介绍
  9. phpstorm 报 expecting statement
  10. 知钱俱乐部 php,知钱俱乐部
  11. Pixelmator for Mac(强大的图像处理软件)
  12. python内置函数表示2的10次幂_Python常见内置函数用法(二)
  13. 数据挖掘-python数据分析与挖掘实战
  14. web应用程序的访问与服务器,本地机的带宽关系 + 带宽详解
  15. 实战案例,手把手教你使用 Tableau 绘制超炫酷可视化图表
  16. 油脂抵近历史高点,棕榈油认购大涨,CCS05继续向下2022.3.1
  17. A session ended very soon after starting. Check that the command in profile解决方法
  18. makefile传字符串给c语言,makefile终极奥义
  19. SIKI学院:MySQL数据库从零到精通:三:课时 4 : 03-服务器端运行通信原理图+课时 5 : 04-游戏服务器端简介
  20. 有两个列表 l1 =[11,22,33] l2 =[22,33,44]

热门文章

  1. Redis系列--内存淘汰机制(含单机版内存优化建议)
  2. java 保留小数点后N位数(若干位),几种实现的方式总结
  3. linux--GCC用法
  4. Chrome浏览器扩展开发系列之十五:跨域访问的XMLHttpRequest对象
  5. 开源项目objective-zip
  6. Native Instruments Battery 4 for mac - 尖端鼓采样器
  7. 「Mac新手操作」:使用力度触控板进行“用力点按”的方法
  8. mac 上 php 验证码不显示图片
  9. :visible.sync 的作用
  10. 通过原生js获取路由url中的参数的实例和讲解