[Paper Reading] TiDB: A Raft-based HTAP Database

Date: 2021.04

目录

===== 1. Introduction

===== 2. RAFT-BASED HTAP

===== 3. ARCHITECTURE

===== 4. MULTI-RAFT STORAGE

===== 4.1 Row-based Storage (TiKV)

===== 4.1.1 Optimization between Leaders and Followers

===== 4.1.2 Accelerating Read Requests from Clients

===== 4.1.3 Managing Massive Regions

===== 4.1.4 Dynamic Region Split and Merge

===== 4.2 Column-based Storage (TiFlash)

===== 4.2.1 Log Replayer

===== 4.2.2 Schema Synchronization

===== 4.2.3 Columnar Delta Tree

===== 4.2.4 Read Process

===== 5. HTAP ENGINES

===== 5.1 Transactional Processing

===== 5.2 Analytical Processing

===== 5.2.1 Query Optimization in SQL Engine

===== 5.2.2 TiSpark

===== 5.3 Isolation and Coordination

===== 6. EXPERIMENTS

===== 7. RELATED WORK

===== 9. REFERENCES


​​​​​​​

[Paper Reading] TiDB: A Raft-based HTAP Database_第1张图片

 [该图来自网络]

  1. 选择Raft协议来解决数据同步时效性、一致性及高可用的问题
  2. 并在Raft协议中增加一个Learner角色,来解决数据同步到列存,同时不对性能造成影响。
    1. 优化Raft协议提升性能:一定程度异步化
    2. 通过增加readIndex&leaseRead特性,支持linearizable
  3. 列存上借用类Parquet存储结构(LSM-Tree),同时在内存中增加一层 B+Tree,来改善读放大的问题
  4. HTAP混合负载
    1. TP场景:基于percolator实现乐观锁&悲观锁事务
    2. AP场景:RBO & CBO 的评估优化
    3. 混合负载的协同隔离:特定场景进行混合负载查询

===== 1. Introduction

  • RDBMS因为其关系模型强事务保证SQL接口而广受欢迎。然而他们不提供扩展性&高可用能力
  • NoSQLBigtable[12] & Dynamo[36]系统诞生了。他们提供松散的一致性保证扩展性以及可变的数据模型
  • 许多应用仍然需要强事务、数据一致性、SQL接口,所以NewSQL(CockroachDB[38]Spanner[14])系统诞生。
  • 此外,基于SQL的OLAP系统快速发展,像需要 SQL-on-Hadoop 系统

These systems follow the “one size does not fit all” paradigm [37], using different data models and technologies for the different purposes of OLAP and OLTP.

这些系统遵循着 "one size does not fit all" 的模式,针对OLTP&OLAP的不同目的 而使用 不同的数据模型&技术

多个系统来完成TP+AP的能力维护成本高、实时分析最新的数据十分重要(时效性)。

HTAP系统首先需要像 NewSQL 一样支持扩展性、可用性、事务能力,同时还需要在数据新鲜度(freshness)和隔离(isolation)的前提下保证吞吐&延迟

数据新鲜度(freshness):分析查询可以读到多新的数据。// ETL的方式无法做到实时、streaming可以降低同步延时,但是仍然很难保证数据一致性。

隔离性(isolation):保证 OLTP & OLAP 的性能。// in-memory db 可以提供freshness(同机读取),但是很难同时对TP&AP查询提供高性能,因为数据同步&工作负载的原因。而且如果in-memory db部署在单机就无法提供高可用&扩展性

  • 混合负载情况下,MemSQL很难保证隔离性在 [24] 中被确认

 

所以为了保证隔离的性能OLTP & OLAP 需要运行在不同的物理硬件。那么问题的难点就在于解决在单个系统中解决副本间数据时效性以及一致性(维护一致性副本需要高可用[29]的问题。系统高可用已经被 Paxos[20] & Raft[29] 论证实现。那么扩展这些一致性算法来提供HTAP workload就称为了可能

我们提出了 Raft-based HTAP database: TiDB。通过在 Raft 中引入 learner (列存),来从 leader 异步复制日志 构建新的副本解决OLAP的问题。

  1. freshness:这种复制方式几乎不会给 leader 上的事务查询增加负载,同时又可以保证 分析查询的新鲜度。
  2. isolation:使用了不同的副本来进行 TP&AP 查询来避免干扰
  3. optimization:基于行存&列存 来优化HTAP请求
  4. 基于 Raft ,TiDB提供了高可用、扩展性、一致性的能力

该论文贡献如下:

  1. 提出了基于公式算法架构的HTAP系统,并实现了HTAP数据库:TiDB // Section 3
  2. 在 Raft 中引入 learner 来生成一个列存支持AP查询  // Section 2
  3. 实现了一个 multi-Raft 存储系统并优化其读写请求 // Section 4
  4. 为大规模HTAP查询定制 SQL引擎,该引擎可以使用行存&列存 // Section 5
  5. 进行了全面的实验,评估TiDB性能 // Section 6

===== 2. RAFT-BASED HTAP

基于复制状态机来完成数据实时同步,以保证不同的server应对不同的HTAP负载。

Raft协议更加易于理解&实现,所以我们基于Raft来进行扩展。

[Paper Reading] TiDB: A Raft-based HTAP Database_第2张图片

  1. 数据以 行存(row format) 的方式存储在不同的Raft group。每个Raft Group由 Leader&Follower组成
  2. 为每个 Raft Group 添加一个 Learner角色(列存,来 异步复制 Leader的数据。这样 开销极低 且能维护 数据一致性 ,同时还将数据从行存转换为列存
  3. Query optimizer 执行 physical plan时可以选择从 行存 或者 列存 来读取

以 Learner 角色加入的原因:标准Raft协议中,follower可能会成为leader角色,增加follower没法做到资源隔离;增加follower会影响性能(因为增大了majority)。引入 Learner 角色 不会参与到 leader 选举中,也不会增加 quorum,数据复制是异步且实时的。

行存可以利用 索引(index) 有效的进行事务查询,列存可以利用 数据压缩(data compression)& 向量化处理(vectorized processing)。数据同步到learner时进行行列转换,节点独立部署也可以做到资源隔离。

支持 HTAP 数据库,我们还面临一些工程挑战:

  1. 如何扩展 Raft存储系统,以支持高并发? // How to build a scalable Raft storage system to support highly concurrent read/write
    1. 确定一个 partition策略 来将数据打散
    2. 基础 Raft协议 请求顺序执行&quorum,需要更多的资源,导致leader称为瓶颈 [4.1.1]
  2. 如何以低延迟的方式将数据同步给learner,以保证数据新鲜度? // How to synchronize logs into learners with low latency to keep data fresh?
    1. 事务产生日志较大,如何在learner上快速重返 [4.2.1]
    2. schema缺失可能会导致转换失败 [4.2.2]
  3. 如何有效的处理事务&分析查询同时保证性能 // How to efficiently process both transactional and analytical queries with guaranteed performance?
    1. 优化事务&分析查询,使之互不影响 [5 SQL Engine]

===== 3. ARCHITECTURE

[Paper Reading] TiDB: A Raft-based HTAP Database_第3张图片

TiDB兼容MySQL协议,支持MySQL客户端。TiDB有3个核心组件:distributed storage layerPlacement Drivercomputation engine layer

 

distributed storage layer:包含一个行存(TiKV和一个列存(TiFlash。数据在 TiKV按照有序 key-value 结构存储。每个数据元组(Tuple都映射为一个 key-value 结构。key由 tableID & rowID 组成(tableID和rowID都是一个introwID来自于primary key的列,value 就是实际的行数据

[Paper Reading] TiDB: A Raft-based HTAP Database_第4张图片

 [该图来自网络]

编码形式:Key -- {table{tableID}_record{rowID}} ; Value -- {col0, col1, col2, col3}

使用 Range 的策略进行partition(便于range查询),每个分片称为 Region。每个Region有多个副本,并使用 Raft 协议来保证一致性(每个region一个Raft协议)。

Placement Driver负责

  1. 管理region&所在物理资源的对应关系
  2. 自动moveRegion以达到资源均衡
  3. 全局时钟管理,提供自增&全局唯一的时钟 = transactionID
  4. 有多个 PD member组成(高可用&性能),没有持久化状态, 启动时从其他member&TiKV拉取数据

computation engine layer

  1. 无状态&可扩展
  2. 基于成本的优化器 & 分布式执行器
  3. 基于 Percolator[33] 实现 2PC transaction
  4. 可以选择从 TiKV & TiFlash 读取

TiDB符合HTAP数据库要求:

  1. 每个组件都是高可用&可扩展的
  2. 存储节点基于Raft实现一致性
  3. 低延迟保证数据新鲜度
  4. 查询优化器提供分析能力,而对事务查询无影响

===== 4. MULTI-RAFT STORAGE

[Paper Reading] TiDB: A Raft-based HTAP Database_第5张图片

相同的形状表示相同的role

存储层由 TiKV & TiFlash 组成。TiKV 中将 table 数据拆分成多个region存储,每个region都使用 Raft协议 来维持一致性。数据复制到TiFlash时,多个region的数据可能会被merge成一个partition,以加速scan。存储层使用多个raft group管理数据,所以我们称其为 multi-Raft storage

===== 4.1 Row-based Storage (TiKV)

[Paper Reading] TiDB: A Raft-based HTAP Database_第6张图片

[该图来自网络]

  • Region在 TiKV 之间的数据复制依靠 Raft来完成
  • 每个 TiKV Server 对不同的Region可以是leader 或者 follower
  • TiKV 数据是存储在 RocksDB[5] 上的
  • 每个Region最大是 96MB 大小

Leader --> Follower 之间的数据同步流程【基础Raft协议】

  1. Region Leader 收到来自 SQL Engine层的请求
  2. leader 将请求 append 到本地日志
  3. leader 将 log entry 发送给 follower(follower也会将日志append到本地)
  4. leader 等待 follower 响应,如果超过 quorum 的 follower 成功,那么leader commit 这条日志并将其apply到本地
  5. leader 将结果发送给 client,并继续处理其他请求

上述基础的Raft协议保证了数据的一致性以及高可用,但是没法提供很好的性能,因为上述操作是串行的,而且可能有大量的IO负载

===== 4.1.1 Optimization between Leaders and Followers

优化点1:第二步(写本地log)和第三步(发送给follower)可以并行执行,因为他们之间没有依赖

优化点2:leader批量发送log给follower,并无需等待follower返回。如果中间有失败的log,这里会retrans

优化点3:leader在其他线程中异步apply log,这里没有不一致风险

优化后数据同步流程:

  1. Region Leader 收到来自 SQL Engine层的请求
  2. leader并行的append log,同时将log发送给follower
  3. leader 持续的接收客户端请求,并重复步骤2
  4. leader commit log,并将他们发送给其他线程进行apply
  5. apply log后,leader将resp发送给client

===== 4.1.2 Accelerating Read Requests from Clients

TiKV提供 linearizable 的读取语义:当在 时间t 进行读取时,获得的结果一定不会是时间t之前的版本。

这个需求可以基于 Raft 实现:对每个 read 请求下发一个log entry,并等待该 log entry commit才返回结果。然而这种方式对IO、同步时效性都有要求,所以这里我们需要规避过程中的日志同步

Raft 保证当数据成功写入以后,leader返回响应结果都无须日志交互。然而在数据读取过程中,如果发生 leader election,就无法保证从leader读取了,也就不能保证返回了最新的数据

比如 t时刻 从leader读取,此时的apply index 为 t-2,而 t-1时刻 发生了 leader选举并产生了一条日志,而当前节点并未感知这些操作,那么返回的结果就不是最新的

为了保证从leader进行读取,TiKV进行了如下优化:

read index:当leader收到 read请求后,会记录当前的提交index为read index。随后发送心跳确认自己的leader地位,如果自己是leader,那么等待本地的apply index >= read index 再返回给 client。

  • 这个等于是上面等待机制的一种优化实现,只不过不再需要日志同步,而是依靠用户请求的日志同步就可以了。但是这里面虽然确认了自己的leader角色,却没法一直保证自己的leader角色,所以下面有lease read的机制来做这个保证。这里同时还有另外一个问题,如果用户下发该读请求以后没有写请求,即apply index一直不推进呢?(这里应该也需要额外的机制保证

lease read:该机制可以降低read index的网络负载,leader & follower约定一个lease period,在此期间内,follower不发起竞选

follower read:为了减轻 leader 的读取压力,可以从follower上读取。follower收到read请求后,向leader询问最新的 read index,并等待本地的 apply index >= read index才返回给client

===== 4.1.3 Managing Massive Regions

Servers&数据量大小是动态变化的,这容易导致server之间的region不均衡。

PD 负责调度region的副本数量及其location,一个原则是 region最少有3个副本在不同的TiKV。PD会通过心跳收集不同server上的信息,并监控其workload,将hot region进行迁移

而管理大量的region需要发送 heartbeat并管理元信息,这会增加一些网络以及存储负载。这里会根据负载动态调整心跳频率

===== 4.1.4 Dynamic Region Split and Merge

hot&large的region需要进行split以均衡负载,small&cold region需要merge以减少网络&CPU负载。PD会动态的进行regionsplit&merge

Split操作将region拆分成几个连续的region,最右侧的region接管原Raft Group,其他region使用新的Raft Group:

  1. PD发送 split 命令给Region leader
  2. Region leader将请求转换为log,并replicate到follower
  3. 当log复制到quorum,leader commit log并apply command。apply操作更新origin region的range及epoch,并创建新的region
  4. 每个新创建的region,都会有对应的Raft state machine创建并组成Raft group。leader将split结果汇报给PD

Merge region是split的反向操作,merge操作需要通过2阶段操作的方式完成:停止一个region的服务,由另外一个reigon接管。这里没法使用简单的log replication来完成region的merge

===== 4.2 Column-based Storage (TiFlash)

TiFlash以learner的角色加入到Raft group中,仅接收Raft log并将其转换为行存,而不参与Raft的日志提交&选举,所以几乎不对TiKV造成影响。

可以通过 'ALTER TABLE x SET TiFLASH REPLICA n;' 来修改列存的副本数(n),默认为1.

TiFlash也会做partition,每个partition会包含TiKV中的几个Region,方便做range scan。

TiFlash初始化:1. leader 发送 snapshot 给 learner;2. learner 监听 Raft log。learner接收Raft log依次进行 replaying the log, transforming the data format, updating the refered value in local storage

===== 4.2.1 Log Replayer

[Paper Reading] TiDB: A Raft-based HTAP Database_第7张图片

raw log: {transaction id} {operation type} {transaction status} {operation data} , transaction status: [transaction status][@start_ts][#commit ts]

column data: operation types, commit timestamps, keys, two column data

为了保证 linearizable的语义,TiFlash FIFO地进行日志重放:

  1. Compacting log:Transaction log会有3中状态:prewritten,committed,rollbacked。rollbacked的日志不需要写入磁盘,compact删除rollback日志及其对应的prewritten log。并将合法的日志写入buffer中
  2. Decoding tuples:清理transaction相关的冗余日志,解析后的tuples写入row buffer
  3. Transforming data format:如果row buffer中的数据大小超过限制或者驻留在row buffer的时间超过限制,那么会将这些数据转换为columnar data并写入本地存储。转换操作依赖schema,定期从TiKV同步

===== 4.2.2 Schema Synchronization

为了保证log能转换为列存,learner需要感知schema,而这些schema存储在TiKV上。为了降低schema同步频率,learner节点维护一个schema cache

schema syncer负责从TiKV同步schema到本地cache。有2种同步机制:

  1. 定期同步
  2. 按需同步:发现schema过期(比如column数量不匹配)

===== 4.2.3 Columnar Delta Tree

[Paper Reading] TiDB: A Raft-based HTAP Database_第8张图片

设计了一个薪的列存引擎:DeltaTree,来保证高效的读写列数据。

在DeltaTree中,delta updates & stable data是分开存储的。在stable space中,partition的数据像chunk一样存储。在delta space中,数据按照TiKV生成的顺序存储。

这个存储结构比较类似 Parquet [4] ,不同的是,TiFlash将row group及其元信息分开存储,以便于并行更新文件。TiFlash 使用 LZ4 [2] 来将数据压缩存储到磁盘上

新写入的deltas都是原子的增删操作,他们被cache在内存并持久化到磁盘。这些数据是按序存储的,所以等同于实现了 Write-ahead log (WAL)

这些delta存储在大量的小文件汇总,所以引入读取的时候引入额外的IO负载(读放大)。为了降低影响,定期将这些小文件compact。内存中cache的数据可以加速读取最新数据的响应时间facilitates reading the latest data并采用LRU的方式淘汰

当进行数据读取的时候,需要读取所有的delta file&以及对应的stable file,因为无法确定相关delta文件分布,所以这里会有读放大(read amplification)的问题

此外,许多delta文件可能存储无用的数据,这里有空间放大(space amplification)的问题,浪费存储空间并减慢与stable层merge的速度.

所以我们定期将delta文件与stable进行合并。

而由于key在delta层是无序的,所以无论是进行delta层的merge,还是进行delta层与stable层的compact,亦或是读取数据的时候需要遍历delta&stable层,代价都是昂贵的。因此这里针对delta层构建了一个 B+Tree,B+Tree中的数据按照key×tamp进行排序,这样可以便于进行对keys进行更新 或是 对单个key进行查询(point select

这里做了一个简短的时间对比 DeltaTree 与 LSM-Tree [28] 的性能。基于sysbench [6] 压测,LSM-Tree使用universal compaction而不是level compaction(ClickHouse也是使用这种方式)

[Paper Reading] TiDB: A Raft-based HTAP Database_第9张图片

可以看到,DeltaTree的读性能是LSM-Tree的2倍(在测试的几组数据量&transactional load下都是这样),这是因为DeltaTree每次读操作都是需要读取一次delta层(因为有B+Tree索引),而LSM-Tree需要访问多次。然而 DeltaTree的写放大是LSM Tree的4倍。(// TODO 为啥会有写放大?

Summary DeltaTree,主体上还是一个2LSM-Tree结构(Stable&Delta层),Stable层理解为是实际的数据存储,Delta层理解为是WAL log,所以等于是定期的快照+增量log的形式。

那么在这样的结构下一些问题(根因上还是因为Delta层是不断appendlog造成的):

比如无法确定keyDelta层归属的文件而引入的读放大问题,为了解决这个问题,构建了一层B+Tree索引,拥有了这个索引其实不太需要进行Delta层的merge

比如Delta文件可能存储无用数据而导致写放大的问题,为了解决这个问题,需要不断的进行compact(可能是Delta层内部的compact,可能是Delta&Stablecompact

===== 4.2.4 Read Process

为了满足snapshot isolation,learner read 和 follower read相似,都是通过read index的方式来完成。当 learner节点收到read请求后,leader节点发送read index来获取可以满足timestamp的最新数据,leader将相关日志发送给learner,learner replay日志后相应请求

===== 5. HTAP ENGINES

提供SQL Engine 来支持评估事务&分析查询:

  1. 使用percolator模型 实现乐观锁&悲观锁的分布式事务
  2. 使用基于规则&代价的优化器、索引、算子下推来加速分析查询

HTAP查询可以在独立的物理资源上运行,并且能同时从行列进行查询来

===== 5.1 Transactional Processing

TiDB提供 snapshot-isolationSI & repeatable readRR级别的事务支持:

  • SI:Transaction中所有的请求都会读取到一个一致性版本的数据
  • RR:Transaction中不同的statement可能读取不同的数据,但是repeating a read(相同时间戳)会读取到相同的数据

我们使用 multi-version concurrency controlMVCC来实现事务支持,同时避免了 读写锁 以及 写写冲突

Transaction由3个组件来协同完成:

  • SQL Engine:协调事务,接收客户端请求,将其转换为KV结构,并将事务使用2阶段提交的方式写入TiKV
  • PD:管理region及其所属位置,提供全局严格递增的时间戳
  • TiKV:提供分布式事务接口,实现MVCC并持久化数据

基于 Percolator 模型实现乐观锁(optimistic lock)&悲观锁(pessimistic lock)事务:选择一个key作为primary key,并使用它来表示事务状态。基于2PC来实施事务

[Paper Reading] TiDB: A Raft-based HTAP Database_第10张图片

乐观事务执行流程:

  1. 收到begin命令后,SQL Engine 从 PD 获取一个时间戳作为 start_ts
  2. SQL engine执行每个DML时,会TiKV读取数据并写入本地缓存。TiKV返回的数据为最新提交(commit_ts)且在本次 start_ts 之前的数据
  3. 当SQL Engine收到commit命令后,开始执行 2PC:首先随机选择一个key作为primary key,并并行的锁定所有的key,然后向TiKV节点发送prewrite请求
  4. 如果所有的prewrite请求都成功,那么SQL Engine从PD请求一个时间戳作为 commit_ts,并发送commit命令给TiKV,TiKV commit primary key并返回成功
  5. SQL Engine向client返回成功 // primary key 提交成功即为事务执行成功
  6. SQL Engine commit随后的keys,并清理相关lock,同时并行的发送commit命令给TiKV

乐观锁事务&悲观锁事务的主要区别就是 何时来获取锁?

  • 乐观锁事务是在prewrite阶段来获取锁(step3
  • 悲观锁事务在每次DML执行的时候就会获取锁(step2),意味着prewrite不会因为冲突而导致失败。

悲观锁事务在每次DML的时候都会获取tsfor_update_ts)并lock相关的key,基于该ts进行本次请求的读取(RR),发生冲突也只会进行局部重试

对于悲观锁事务,用户可以选择RC隔离级别,以减少冲突获取更好的性能。区别在于:RR事务中,如果读请求访问的key被其他transaction锁定,必须返回conflict;而RC事务会忽略这种锁而进行读取

TiDB实现分布式事务而无需中心化的锁管理,具备更好的扩展性。

Timestamp从PD获取,每个Timestamp包含physical time&logical time 2部分,pt精确到ms,lt占用18bit(支持2^18个时间戳)。理论上 PD可以支持每毫秒 2^18个时间戳,实际上也可以达到每秒100w的时间戳生成。

===== 5.2 Analytical Processing

该section描述对 OLAP请求的优化,包含optimizerindexespushing down computation

===== 5.2.1 Query Optimization in SQL Engine

[Paper Reading] TiDB: A Raft-based HTAP Database_第11张图片

[该图来自网络] 

TiDB实现2个阶段的查询优化:

  • rule-based optimization(RBO)生成逻辑计划:cropping unneeded columns, eliminating projection, pushing down predicates, deriving predicates, constant folding, eliminating “group by” or outer joins, and unnesting subqueries
  • cost-based optimization(CBO)将逻辑计划转换为物理计划:基于执行时间来选择目标plan,基于三种扫描策略:扫描行存、扫描列存、扫描索引

索引可以加速数据扫描的代价,创建和删除索引都是在后台异步完成.

每个region都负责存储其管理的数据对应的index,index按照Key-Value的方式存储在TiKV上。

[Paper Reading] TiDB: A Raft-based HTAP Database_第12张图片

[该图来自网络]

 

unique key编码形式:Key -- {table{tableID}_index{indexID}_indexedColValue} ; Value -- {rowID}

unique key编码形式:Key -- {table{tableID}_index{indexID}_indexedColValue_rowID} ; Value -- {null}

Index Intersection - 多个候选索引的选择方式:基于多个索引返回的结果进行merge,来返回精确结果

物理计划使用 pulling iterator [17] 模型执行,算子下推到 TiKV的coprocessor,coprocessor支持逻辑运算、算数运算、其他常用计算,一些情况也可以执行aggregate&TopN

===== 5.2.2 TiSpark

[Paper Reading] TiDB: A Raft-based HTAP Database_第13张图片

TiSpark集成 TiDB:1. 从TiKV读取元数据;2. 从PD读取ts,以获取一致性数据;3. 支持算子下推;3. 自定义从TiKV or TiFlash 读取数据

TiSpark与常用connector不同:

  1. 可以并行读取不同region的数据及索引
  2. 修改Spark生成的plan,支持算子下推
  3. 使用事务来读取数据

===== 5.3 Isolation and Coordination

AP&TP查询混合使用会导致较大的延迟,在 [24, 34] 中被验证。为了规避这个问题,我们调度事务查询&分析查询到不同的engine上,并且将TiKV&TiFlash部署在独立的机器

TiKV&TiFlash上的数据是一致的,所以我们的查询优化器可以从更大的物理计划中选择,也可以从TiKV&TiFlash中都读取数据。所以这里有3种扫描场景:扫描行存、扫描列存、扫描索引。

三种扫描方式(行存、列存、索引)的评估方式是不同的:行存&列存按照primary key排序,索引提供多种排序方式。

[Paper Reading] TiDB: A Raft-based HTAP Database_第14张图片

tuple/column/index 的平均大小:S ;tuple/region 的数量:N;scan&seek代价:f

隔离性标准:

  1. 分析查询只有小的范围查询 或者 点查,才会从follower读取数据,访问数据量最多 500MB
  2. 事务查询可以访问列存来check某些约束(比如唯一性约束)。为特定的表设置多个列存副本,其中一个副本专门用于事务查询

===== 6. EXPERIMENTS

[Paper Reading] TiDB: A Raft-based HTAP Database_第15张图片

PD生成时间戳,不成为瓶颈。6server获取时间戳,每秒可以获取60w+

复制延迟:HTAP负载下可以保持1s以内的复制延迟,延迟程度取决于数据量大小

===== 7. RELATED WORK

构建HTAP系统的常见方法:

  1. 从现有数据库演进 -- evolving from an existing database
  2. 扩展开源分析系统 -- extending an open source analytical system
  3. 从头构建 --  building from scratch

TiDB是从头构建的,并且在架构、数据组织、计算引擎、一致性保证与其他系统都有所不同

从现有数据库演进 -- evolving from an existing database,成熟的数据库提供HTAP服务基于现有产品,并focus在加速AP查询上。他们使用不同的方式来实现数据一致性&高可用(TiDB使用Raft来实现数据一致性&高可用)。

  • Oracle [19] 引入 in-memory option成为业界第一个双格式内存RDBMS,引入内存态为了支持AP查询而不影响TP查询。该列存是一个只读快照,保持某个时间点的一致性,并使用完全的在线填充机制
  • SQL Server [21] 使用2个独立的引擎,Apollo column storage支持AP负载,Hekaton in-memory engine支持TP负载。数据定期从Hekaton复制到Apollo
  • SAP HANA  [22] 使用不同的数据组织形式支持TP&AP,AP系统异步的复制TP数据。这不能保证一致性,而且TP部署在单节点上,也不能很好的保证高可用

扩展开源系统 -- Transforming an open-source system,Spark是一个开源的分析框架,其需要一个TP模块来实现HTAP,很多系统按照这种方式来完成

  • Wildfire [10,9] 在Spark基础上实现HTAP。其执行TP&AP在同样的数据组织形式上(Parquet),使用last-write-wins来实行更新并支持快照读,未使用共识算法直接进行数据复制。然而其存在延迟问题
  • SnappyData [25] 使用Spark计算框架,之下使用GemFile 存储(in-memory, scale-out transaction store)

从头构建 --  building from scratch,许多新的HTAP系统研究了 HTAP 的不同方面:使用内存计算来提升性能、优化存储&可用性。但是他们不能像TiDB一样同时支持高可用、一致性、扩展性、数据新鲜度&隔离性

  • MemSQL [3]、HyPer [18]、BatchDB [24] 、Lineage-based data store [35] 、Peloton [31]
  • Cockroach DB [38] 无法提供专属的OLAP or HTAP能力

===== 9. REFERENCES

Theory

  • 《Hybrid Transactional/Analytical Processing: A Survey》 HTAP 提出 [30]
  • 《What's Really New with NewSQL?》 NewSQL 提出 [32]
  • "one size does not fit all" [37]

Algorithm / Data struct

  • LZ4 [2]
  • LSM-Tree [28]
  • Paxos [20]
  • Raft [29]

Research

  • Bridging the Archipelago between Row-Stores and Column-Stores for Hybrid Workloads. [8]
  • Scalable SQL and NoSQL data stores. [11]
  • SQL-on-Hadoop systems [16]
  • 《Scaling Up Mixed Workloads: A Battle of Data Freshness, Flexibility, and Scheduling [34]

Product

  • ClickHouse [1]、Parquet [4]、RocksDB [5]、Bigtable [12]、Spanner [14]、Percolator[33] 、DynamoDB [36]、Cockroach DB [38]
  • TiDB [7]
    • 《An Extensible and Parallel Query Evaluation System》(pulling iterator -- TiDB进行 物理计划使用的模式) [17]
  • Oracle [19]
    • Oracle high availablity for HTAP [27]
  • SQL Server [21]
    • 《Interleaved Multi-Vectorizing》(SIMD -- SQL Server进行data scan的方式) [15]
  • Wildfire [10,9]
    • Wildfire indexing [23]
  • MemSQL [3]、HyPer [18]、SAP HANA  [22]、BatchDB [24] 、SnappyData [25] 、ScyPer [26]、Peloton [31]、Lineage-based data store [35]

Tools

  • Sysbench [6]
  • CH-benCHmark [13]

你可能感兴趣的:(Paper,Reading,database,big,data)