Tiflash-TiDB HTAP架构核心模块


说重点

公司用了TiDBv4.0有一段时间了,业务上也多了另一种优化选择,今天找个时间,对照官网和一些架构设计及文稿综合一下,总结下自己对TiFlash的整体看法

TiDB-v4.0引入了TiFlash,架构图官网给出如下,简而言之有以下特点:

- 列存扩展:通过raft learner的复制协议,配合MVCC获取快照隔离级别,解决隔离性和列存同步问题

- 借助 ClickHouse 高效实现的协处理器层

- 与TiKV一样,有region的单位,合并和分割

在我看来,以此实现的比较重要的三点:

1.实时更新的列存

2.Multi-Raft的复制体系

3.根据代价的智能选择

TiFlash的官网架构设计图


1.TP和AP的存储格式

TP和AP对应的是行存和列存,然而这点在内存中体现差异并不大.由此引出SAP Hana的作者Plattner使用 In Memory + 列存技术 同时处理OLTP和OLAP,2014年Gartner提出的HTAP概念,也是针对内存进行计算设计.

关键点问题:列存不适合TP类场景,这是个common sense,但是不是所有人都知道Why?

数据快速访问需要仰赖 Locality,简单说就是根据访问模式,要读写的数据尽量放在一起。并不在一起的数据需要额外的 Seek 并且 Cache 效率更低。

行存和列存,去除 encoding 和压缩这些因素,本质上是针对不同的访问模式提供了不同的数据 Locality。行存一次访问一整行数据就会得到很好的速度;列存将同一列的数据放在一起,那么每次只获取一部分列的读取就会得到加速;另一方面,列存在传统印象里更新很慢也部分是因为如果使用 Naive 的方式去将一行拆开成多列写入到应有的位置,将带来灾难性的写入速度。这些效应在磁盘上很明显,但是在内存中就会得以削弱,因此这些年以来我们提起 HTAP,首先想到的是内存数据库。

但是内存毕竟成本较高,暂时只能在特殊领域得到硬要,所以,HTAP的设计突破口还在磁盘而非内存.但是譬如PAX格式,是在同一个存储引擎中通过算法去柔TP和AP,但始终突破不了Locality,在优秀的架构设计也很难逼近两侧最优解,实际场景实现更会复杂数据.

TiDB以HTAP为宣传理念,知道PAX的坑,那么怎么绕过去? --用模块化解决问题

模块化的思想贯穿TiDB设计理念始终,TiDB,PD和TiKV的分层模块切割都表现了这种架构设计思路.TiDB拿出的答案是,通过Raft 剥离/柔和 行存和列存 ,把难以实现的突破口通过解耦合的方式避免在一个存储引擎中解耦合,这也跟Raft根据Paxos实现的简化思想大道同路.这样一是减少了产品开发周期,二是引进了列存(ClickHouse),把行存和列存放在两个盒子里,分而治之.

2.如何实现列存的数据更新和实时同步速度

TiDB有了松耦合设计和ClickHose+TiKV,怎么实现TP和AP根据主键的实时同步?--Delta Main

传统的Hadoop等通过大量覆盖和去重达到列存更新的目的,但是时间消耗为T+1,抛弃实时更新获取批量告诉加载.HTAP的目标,必须要保证列存的更新速度和行存一样快,才能实时更新.

TiDB采取了业界通过的做法 Delta Main,通过写优化方式存储变更数据,逐步将更新部分归并到读优化的主列存去,保证归并速率,这样数据大部分就能使在读优化区使用进而保持性能.简而言之就是 写按照写入顺序而非主键顺序排序,大大提高写的速度,读按照 Row-Group 按列切割,并排序后压缩.C-Store作为列存的鼻祖,就是这种设计的一种实现.以下是设计架构图


TiDB的列存引擎TiFlash-用DeltaTree实现思路:

 - 分成Delta space(优化写入) 和 Stable Space(优化读取)两个空间,宏观上降DeltaTree将数据切分,类似Region的概念,每个数据范围行为一个片段,每个片段都有Delta space和Stable space.这样在归并是无序重写所有数据,减轻压力

-  Delta space:按照写入顺序不断追加数据,等达到阈值则归并到 Stable区,辅以内存中B+Tree索引,这样虽然物理有序保证不了(以为会大大降低排序速度),但逻辑有序是可以保证的,免去归并前排序代价.

- Stable Space:切分数据,排序后归并压缩存储.利用已经逻辑有序的数据块,对于正在读取但仍未归并到Stable Space的数据,进行在线归并.

到此,解决了列存更新问题

3.从行存-->复制到列存的实现

松耦合的存储引擎,行存列存不再一个模块内,就要实现从行存中复制数据到列存.传统的主从复制,如Mysql利用binlog这样的 高层级复制,可以封装细节,回放binlog日志即可,但是重大问题会把TiDB这样一个分布式系统变成因为binlog的汇聚和排序降维打击成单点系统.

于是利用 low level的日志复制,在raft从仍进行数据复制,raft log细节,TiFlash被设计成一种特殊的TiKV节点,享受Multi-Raft体系的遍历,跟TiKV一样将很多扩容,容错等细节都交给PD处理.当然也是经过开发人员的巨大努力实现.

于是有了TiFlash,对比主从复制和统计器行列双写,AP和TP部分完全独立运行,扩容.需要AP则增加TiFlash节点,需要TP增加TiKV节点.两者互不干扰.

同时Region Leader的额副本单独与列存侧的副本进行沟通,无序中间存储介质,Region分裂则列存副本分裂,TiKV热点打散迁移,列存迁移.得益于TiDB的Multi-Raft体系.



Multi-raft下的log

传统意义,如果副本一直,则要同步复制,这样分布式环境上,网络延迟和列存节点高压,都会对TP业务造成冲击,为了保证数据一致性,列存必须更新完按在返回.而Raft解决了这个问题,TiFlash通过Learner角色介入Raft体系,不投票不候选,只异步同步Log的方式加入集群,这样不会影响TP的业务,TiKV无序等待TiFlash的数据同步,完成正常的行存副本容错复制就可以返回事务.

那么问题来了,行存和列存间的数据一致性怎么保证?

TiDBv4.0在这点上选择了一种一致的逻辑读取结果,放弃时刻的数据上物理一致.即保证最终读取得到最新的一致性数据.当读取发生,列存向行存发起校对请求,得到收到请求顺序的日志序号,TiFlash等待数据复制进度追上校对结果,这样TiKV写入最新数据保证能从TiFlash上读取,配合时间戳和MVCC,提供和TiKV一样的强一致保证,放心大胆的在一个查询中混合两种存储引擎



4智能选择

TiFlash默认策略CBO,根据代价优化自动选择行存或者列存.技术上来说并无太多新意.从实际体验,TiDBv4.0通过这种巧劲完成了传统的TP+报表扩展到HTAP业务.AP和TP边界模糊了起来.一个业务里既能得到行存的集体信息,也能计算出想要的报表数据,虽然需要大量的资源就是了.

最后,放上官网的部署网址,https://docs.pingcap.com/zh/tidb/stable/use-tiflash
```

ALTER TABLE table_name SET TIFLASH REPLICA count

```

你可能感兴趣的:(Tiflash-TiDB HTAP架构核心模块)