データローミング - X-エンジンSIGMOD論文の紹介

ほとんどの人は永遠の家(ホーム)を検索し、少数の人々は永遠のコースを追求しています。 ----ヴァルター・ベンヤミン

背景

自習データベースPOLARDBのXストレージエンジンとしてOLTPデータベースのストレージエンジンの研究から、X-エンジンアリデータベース製品部門は、それが広く歴史ライブラリを釘付け、取引履歴のライブラリーを含め、多くのアリ当社グループの社内業務システムで使用されてきましたコアアプリケーション、ビジネスのためのコストの大幅な削減だけでなく、二から一一大きなプロモーションの主要なデータベース技術は、数百倍の通常のトラフィックの影響を生き残りました。

紙に書いたX-Engineのチーム:今年初めに、データベースのストレージエンジン上の私たちのオリジナル作品の詳細な説明「X-Engineの大規模なEコマーストランザクション処理のために最適化されたストレージエンジンは」SIGMODてきました'19工業用トラックのレセプション。SIGMODは、最も重要で最も影響力のある会議データベースフィールドの1、6月の終わり、今年でアムステルダム、オランダで開催されます、そして、博士はタオ鄭魯迅X-Engineのチームが探求するすべての人を歓迎し、会議でのシェアを行います。

この記事では、読者がより良い詳細を理解するために、本論文の主要な解析を目指しています。

データベースのストレージエンジンは、開発の数年後、良い成熟した製品の多くがあった、古い技術です。ストレージエンジンのすべての種類は、インデックス、キャッシュ管理、トランザクション処理で編成された、クエリの最適化の側面には、細心の研究を行っています。(データベースのストレージエンジンは、あなたが私の前に参照することができます能力の種類、持つべき記事でもそう、)、この領域の進化は、毎年、多くの新技術の出現を続けています。近年では、LSM(ログ構造Merge-木) 長年にわたって技術自体の周りには、何も新しいものではないではありませんが、いくつかのより以前KVストレージシステムに適用されるが、構造は、ますます注目を受けています近年では、典型的なデータベースのストレージエンジンの分野、RocksDBに現れ始めました。

LSMは、その単純さ、及び第二の、異なる特性のため、第一、ファッショナブルになってきています。簡単なモデルが追加された書き込み、既存のデータを更新しない、単純な論理シーケンスにデータを整理し、結果の特性が強く、弱い読み取りを書くことで、読み取り専用の永続的なデータ圧縮が簡単ます。しかし、ほとんどのデータベースが実際より少なく直接LSM構造を使用して読み書きされているシナリオが短い利点の提供を受けることが、あなたは他の方法を探したい、適切でないかもしれません。

アーキテクチャ

X-エンジン目標は、低コスト、高性能の汎用ストレージエンジンとしてあり、インフラストラクチャとしてLSMを使用して、よりバランスのとれた読み取りの追求と、主にいくつかの方向を中心に、多くの中でそれを改善するため、パフォーマンスを書いて、:1。自然の利点の使用は、書き込み性能を最適化し続けます。2.システムのパフォーマンスが安定した作り、システムのパフォーマンスへの影響を軽減するために圧縮を最適化します。3.読み取り専用データ層の永続性の使用は、利点は、圧縮コストを発揮します。4.天然の層状構造の使用は、能力、コストを低減すること、ハードウェア階層コールドの組み合わせを使用します。5.アクセス機構の使用と洗練されたキャッシュは、欠点を補うためにパフォーマンスをお読みください。

以下X-エンジンの全体的なアーキテクチャ、冷LSMの代わりに、データ自体に基づいて永続的な層状階層データ、データ層とデータ格納メモリを更新するために使用される熱、メモリデータベース(ロックフリーインデックス構造/多量を用いる技術スループットを向上させるために、トランザクションのいくつかの段階まで平行に、トランザクション処理、パイプライン処理機構を設計トランザクション処理の性能を向上させる)だけ追加。冷(温度)の低いアクセス頻度が段階的又は格納される現在のリッチ階層(NVM / SSD / HDD)を有する記憶装置に永続的なストレージ階層にデータをマージします。マージプロセス中に多重化されたデータは、LSM微調整の形状は、減少したように、我々は、ホットより濃縮されたデータ更新機能と性能ロット最大衝撃圧縮プロセス、主データの記憶粒度が分割され、最適化I / Oと計算コスト、大幅に拡大空間マージ処理を軽減しつつ。同時に、アクセス制御と、より詳細なキャッシュメカニズムの使用は、読み取りのパフォーマンスを最適化します。

X-エンジンは、LSMベースのアーキテクチャなので、すべてのものだけでなく、LSM自体からですので。

LSMの基本的なロジック

データ構造LSMの旅、書き込みWALは(ログ先行書き込み)を開始し、最初の足掛かりTaの全ライフサイクルであるMemTableに入ります。その後、より安定した媒体に刻まフラッシュ操作Taが、締固め作業がより遠大Taが起こったか、途中で捨て、まもなくときのTa後継者に依存します。

LSMは、場所を更新しない、すべての書き込み操作の本質であるが、追加の方法でメモリを書くこと。それぞれの永続ストレージに書き込まれた層(レベル)を、凍結し、ある程度のを書きました。すべての行がいずれかのメモリまたは永続ストレージに、良いソート保存した後、主キー(鍵)の両方に書き込まれました。メモリの一種でも読み取り専用永続ストレージ構造の全体一種として永続ストレージ内のメモリ・データ構造(Skiplist、Bツリー、等)です。

トランザクション処理をサポートするために、通常のストレージシステム、特にACI、それによってトランザクションごとに同時とは別の視力干渉を構築、時間ディメンションを追加する必要があります。各トランザクションエンジンは、グローバルシーケンサと単調に増加するトランザクションのバージョン番号(SN)を付与する格納、各トランザクションレコードは、それにより、分離機構のトランザクションを達成する、個々のトランザクションの間に可視性を決定するためにSNに記憶されています。

LSMストレージ構造は他のアクションをしない、書き続けた場合は、次のように最終的な構造は次のようになります。

SNが持続データがもはや変更されないことができた業務の注文書の各層の範囲を特定することに留意されたいです。各レイヤデータがキーをソートされ、層の間の主な範囲が重複します。

この構造は非常にフレンドリー書き込まれる限り、メモリがクラッシュリカバリの実現のために完了している最新のリストに追加されるように、単純に(ログをやり直し)WALを記録し、新しいデータが古いバージョンを上書きしませんので、追加記録は、自然を形成することになりますマルチバージョンアーキテクチャ。

さまざまなレベルで分散している別のトランザクションがレコードをコミット生成、鍵が異なる中で散乱される、より多くのように蓄積された凍結された持続性レベルの問い合わせが同じキーの複数のバージョンに悪影響を与えるであろうと考えられることがあります異なるレベルは、読み出し動作として順次走査は、最終結果を生成するために、個々の層を見つけてマージする必要があります。

LSM引入了一个compaction的操作解决这个问题,这个操作不断的把相邻层次的数据合并,并写入这个更低层次。而合并的过程实际上就是把要合并的相邻两层(或是多层)数据读出来,按key排序,相同的key如果有多个版本,只保留新(比当前正在执行的活跃事务中最小版本号新)的版本,丢掉旧版本数据,然后写入新的层。可以想见这个操作非常耗费资源。

LSM compaction操作,有几种作用,一是为了丢弃不再被使用的旧版本数据,二是为了控制LSM层次形状,一般的LSM形状都是层次越低,数据量越大(倍数关系),这样放置的目的主要是为了提升读性能。

一般来讲,任何存储系统的数据访问都有局部性,大量的访问都集中在少部分数据上,这也是缓存系统能有效工作的基本前提,在LSM存储结构中,如果我们把访问频率高的数据尽可能放在较高的层次上,保持这部分数据量规模,可以存放在快速存储设备中(比如NVM,DRAM),而把访问频率低的数据放在较低层次中,使用廉价慢速存储设备存储。这就是X-Engine的根据冷热分层概念。

要达到这种效果,核心问题是如何挑选合适的数据合并到更低的层次,这是compaction调度策略首先要解决的问题,根据冷热分层的逻辑,就是优先合并冷数据(访问频率相对低)。识别冷数据有很多方法,对于不同的业务不尽然相同,对于很多流水型业务(如交易,日志系统),新近写入的数据会有更多的概率被读到,冷热按写入时间顺序即可区分,也有很多应用的访问特征跟写入的时间不一定有关系,这个就要根据实际的访问频率去识别冷数据或是热数据。

除了数据热度以外,挑选合并数据还有其他一些维度,会对读性能产生影响,比如数据的更新频率,大量的多版本数据在查询的时候会浪费更多的I/O和CPU,因此需要优先进行合并以减少记录的版本数量,X-Engine综合考虑了各种策略形成自己的compaction调度机制。

refined LSM

上面是LSM宏观逻辑结构,如果具体来论读写操作和compaction如何进行,就需要探讨每一层的数据组织方式,

每个LSM变种的实现各不相同。

X-Engine的memtable使用了Locked-free SkipList. 求的是简单,而且并发读写的性能都比较高。当然有更高效的数据结构,或者同时使用多种索引技术。这个部分X-Engine没有做过多优化,原因在事务处理的逻辑比较复杂,写入内存表还没有成为其瓶颈。

持久化层如何组织更显高效,这就需要讨论每层的细微结构。

数据组织

简单来说,X-Engine的每层都划分成固定大小的Extent,存放每个层次中的数据的一个连续片段(Key Range). 为了快速定位Extent,为每层Extents建立了一套索引(Meta Index),所有这些索引,加上所有的memory tables(active/immutable)一起组成了一个元数据树(Metadata Tree),root节点为"Metadata Snapshot", 这个树结构类似于B-Tree,当然不尽相同。

需要注意的是,X-Engine中除了当前的正在写入的active memtable以外,其他结构都是只读的,不会被修改。给定某个时间点, 比如LSN=1000, 上图中的"Metadata Snapshot1"引用到的结构即包含了(LSN=1000)时刻的所有的数据的快照(这也是为什么这个结构被称为Snapshot的原因)。

即便是Metadata结构本身,也是一旦生成就不会修改。所有的读都是以这个"Snapshot"结构为入口,这个是X-Engine实现SI隔离级别的基础。之前讲过随着数据写入,累积数据越多,需要对memtable冻结,flush, 以及层与层的compaction. 这些操作都会修改每层的数据存储结构,所有这些操作,都是用copy-on-write来实现,方法就是每次都将修改(switch/flush/compaction)产生的结果写入新的Extent,然后依次生成新的"Meta Index"结构,乃至新的"Metadata Snapshot",以一次compaction操作为例:

可以看到"Metadata Snapshot 2"相对于"Metadata Snapshot 1"并没有太多的变化,仅仅修改了发生变更的一些叶子节点以及索引节点。这个技术颇有些类似"B-trees, Shadowing, and Clones",如果你读过那篇论文,会对理解这个过程有所帮助。

事务处理

得益于LSM轻量化写机制,写入操作固然是其明显的优势,但是事务处理远不只是把更新的数据写入系统那么简单,这里要保证ACID,涉及到一整套复杂的流程。X-Engine将整个事务处理过程分为两个阶段:读写阶段和提交阶段。读写阶段需要校验事务的写写冲突,读写冲突,判断事务是否可以执行或回滚重试,或是等锁。如果事务冲突校验通过,则把修改的所有数据写入"Transaction Buffer", 提交阶段包括写WAL,写内存表,以及提交并返回给用户结果的整个过程,这里面既有I/O操作(写日志,返回消息),也有CPU操作(拷贝日志,写内存表)。

为了提高事务处理吞吐,系统内会有大量事务并发执行,单个I/O操作比较昂贵,大部分存储引擎会倾向于聚集一批事务一起提交,称为"Group Commit",能够合并I/O操作,但是一组事务提交的过程中,还是有大量等待过程的,比如写入日志到磁盘过程中,除了等待落盘无所事事。

X-Engine为了进一步提升事务处理的吞吐,采用了一种流水线的技术:把提交阶段分为四个独立的更细的阶段:拷贝日志到缓冲区(Log Buffer), 日志落盘(Log Flush), 写内存表(Write memtable), 提交返回(Commit)。我们的事务提交线程到了处理阶段,都可以自由选择执行流水线中任意一个阶段,这样每个阶段都可以并行起来,只要流水线任务的大小划分得当,就能充分并行起来,流水线处于接近满载状态。另外,利用的是事务处理的线程,而非后台线程,每个线程在执行的时候,要么选择了流水线中的一个阶段干活,要么逛了一圈发现无事可做,干脆回去接收更多的请求,这里没有等待,也无需切换,充分的调动了每个线程的能力。

读操作

LSM在处理多版本数据的方式是新版本数据记录会追加在老版本数据后面,从物理上看,一条记录不同的版本可能存放在不同的层,在查询的时候需要找到合适的版本(根据事务的隔离级别定义的可见性规则),一般查询都是查找最新的数据,总是由新的层次(最新写入)往老的层次方向找。

对于单条记录的查找而言,一旦找到便可终止,如果记录还在比较靠上的层次,比如memtable,很快便返回;如果记录不幸已经落入了很低的层次(可能是很随机的读),那就得经历逐层查找的漫漫旅途,也许bloomfilter可以跳过某些层次加快这个旅程,但毕竟还是有更多的I/O操作。X-Engine针对单记录查询引入了Row Cache,在所有持久化的层次的数据之上做了一个缓存,在memtable中没有命中的单行查询,在Row Cache之中也会被捕获。Row Cache需要保证缓存了所有持久化层次中最新版本的记录,而这个记录是可能发生变化的,比如每次flush将只读的memtable写入持久化层次时,就需要恰当的更新Row Cache中的缓存记录,这个操作比较微妙,需要小心的设计。

范围扫描的操作就没这么幸运了。因为没法确定一个范围的key在哪个层次中有数据,也许是每层都有,只能扫描所有的层次做合并之后才能返回最终的结果。X-Engine同样采用了一系列的手段:比如Surf(SIGMOD'18 best paper)提供range scan filter减少扫描层数;还有异步I/O与预取对大范围扫描也有显著的提升。

读操作中最核心的是缓存设计,Row Cache来应付单行查询,Block Cache负责Row Cache miss的漏网之鱼,也用来应付scan;由于LSM的compaction操作会一次大批量更新大量的Data Block,导致Block Cache中大量数据短时间内失效,带来性能的急剧抖动。X-Engine同样做了很多的处理:1.减少Compaction的粒度, 2. 减少compaction过程中改动的数据(见稍后章节) 3. compaction过程中针对已有的cache数据做定点更新。由此可以基本将cache失效带来的抖动降到最低的水平。

X-Engine中的缓存比较多样,memtable也可算做其中一种。以有限的内存,如何恰当的分配给每一种缓存,才能实现价值最大化,是一个还未被妥善解决的问题,X-Engine也在探索当中。

当然,LSM对读带来的也并非全是坏处,除了memtable以外的只读的结构,在读取路径上可以做到完全无锁(memtable也可设计成读无锁)。

Compaction

compaction操作是比较重的。需要把相邻层次交叉的key range数据读出来,合并,然后写到新的位置。这是为前面简单的写入操作不得不付出的代价。X-Engine为优化这个操作重新设计了存储结构。

如前所述,X-Engine将每一层的数据划分为固定大小的"Extent",一个Extent相当于一个小的完整的SSTable, 存储了一个层次中的一个连续片段,其中又会被进一步划分一个个连续的更小的片段"Data Block",相当于传统数据库中的"Page",只不过是只读的,而且是不定长的。

回看数据组织一节中"合并操作对元数据的改变", 对比"Metadata Snapshot2"和"Metadata Snapshot1"的区别,可以发现Extent的设计意图。是的,每次修改对结构的调整并不是全部来过,而是只需要修改少部分有交叠的数据,以及涉及到的"Meta Index"节点。两个"Metadata Snapshot"结构实际上共用了大量的数据结构。这个被称为数据复用技术(Data Reuse),而Extent大小正是影响数据复用率的关键,Extent作为一个完整的被复用的物理结构,需要尽可能的小,这样与其他Extent数据交叉点会变少,但又不能非常小,否则需要索引过多,管理成本太大。

X-Engine中compaction的数据复用是非常彻底的,假设选取两个相邻层次(Level1, Level2)中的交叉的Key Range所涵盖的Extents进行合并,合并算法会逐行进行扫描,只要发现任意的"物理结构"(包括Data Block和Extent)与其他层中的数据没有交叠,则可以进行复用。只不过,Extent的复用可以修改Meta Index,而Data Block的复用只能拷贝,即便如此也可以节省大量的CPU.

一个典型的数据复用在compaction中的过程可以参考下图:

可以看出,对于数据复用的过程是在逐行迭代的过程中完成的,不过这种精细的数据复用带来另一个副作用,即数据的碎片化,所以在实际操作的过程中也需要根据实际情况进行折中。

数据复用不仅给compaction操作本身带来了好处,降低操作过程中的I/O与CPU消耗,更对系统的综合性能产生了一系列的影响。比如compaction过程中数据不用完全重写,大大减少了写入空间放大; 更因为大部分数据保持原样,数据缓存不会因为数据更新而失效,减少合并过程中因缓存失效带来的读性能抖动。

实际上,优化compaction的过程只是X-Engine工作的一部分,还有更重要的,就是优化compaction调度的策略,选什么样的Extent,定义compaction任务的粒度,执行的优先级,都会对整个系统性能产生影响,可惜并不存在什么完美的策略,X-Engine积累了一些经验,定义了很多规则,而探索如何合理的调度策略是未来一个重要方向。

后记

X-Engine是阿里云智能事业群-数据库产品事业部的重要核心技术之一,作为兼容MySQL的数据库POLARDB X的存储引擎,之前是在服务阿里集团业务中逐渐打磨成熟,今年下半年,我们将在阿里云平台上推出MySQL(X-Engine)的RDS公有云服务,为阿里云上的公有云客户提供低成本高性能的数据库服务。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

おすすめ

転載: blog.csdn.net/weixin_43970890/article/details/91554190