Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix session1/charpter 11 tispark-architecture #813

Closed
wants to merge 48 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
a8e409e
Merge pull request #1 from pingcap-incubator/master
tigeriq188 Mar 16, 2020
b0b7a5e
Update tidb-architecture.md
tigeriq188 Mar 16, 2020
02de125
Update tidb-architecture.md
tigeriq188 Mar 16, 2020
446f2c3
Update session1/chapter1/tidb-architecture.md
kissmydb Mar 16, 2020
06e4817
Update tidb-metadata-management.md
tigeriq188 Mar 17, 2020
82d9d77
Update tidb-sql-layer-summary.md
tigeriq188 Mar 17, 2020
6c7d68b
Update session1/chapter1/tidb-architecture.md
kissmydb Mar 18, 2020
2b7bc8e
Update tidb-architecture.md
tigeriq188 Mar 19, 2020
d8a324d
Update scheduling-overview.md
tigeriq188 Mar 31, 2020
80c65b7
Update scheduling-overview.md
tigeriq188 Mar 31, 2020
4c73f0a
Update scheduling-overview.md
tigeriq188 Mar 31, 2020
26e2a22
Update scheduling-overview.md
tigeriq188 Mar 31, 2020
7690792
Update scheduling-overview.md
tigeriq188 Mar 31, 2020
0d20b3e
Update scheduling-overview.md
tigeriq188 Mar 31, 2020
0f99d1b
Update scheduling-overview.md
tigeriq188 Mar 31, 2020
11f334a
Update scheduling-overview.md
tigeriq188 Mar 31, 2020
5547442
Update scheduling-overview.md
tigeriq188 Mar 31, 2020
55118a3
Update scheduling-overview.md
tigeriq188 Mar 31, 2020
5aecbe5
Update scheduling-overview.md
tigeriq188 Mar 31, 2020
cde0dd5
Update scheduling-overview.md
tigeriq188 Mar 31, 2020
3e7e2f5
Merge branch 'master' into master
tigeriq188 Apr 1, 2020
68126f2
Update tiflash-intro.md
tigeriq188 Apr 2, 2020
000bd56
Update tiflash-intro.md
tigeriq188 Apr 2, 2020
10b2439
Update tiflash-intro.md
tigeriq188 Apr 2, 2020
32f626e
Update tiflash-intro.md
tigeriq188 Apr 2, 2020
e631239
Update tiflash-intro.md
tigeriq188 Apr 2, 2020
9121bcc
Update tiflash-intro.md
tigeriq188 Apr 2, 2020
91b034e
Update tispark-intro.md
tigeriq188 Apr 3, 2020
822cf5e
Update tispark-intro.md
tigeriq188 Apr 3, 2020
b832d78
Update scheduling-overview.md
tigeriq188 Apr 5, 2020
0d6be98
Update scheduling-overview.md
tigeriq188 Apr 5, 2020
b6bfacd
Update scheduling-overview.md
tigeriq188 Apr 5, 2020
736f8a7
Update session1/chapter9/tiflash-intro.md
tigeriq188 Apr 5, 2020
9f45e42
Update session1/chapter9/tiflash-intro.md
tigeriq188 Apr 5, 2020
e729381
Update session1/chapter4/scheduling-overview.md
tigeriq188 Apr 5, 2020
ab6b09e
Update session1/chapter11/tispark-intro.md
tigeriq188 Apr 5, 2020
14b4146
Update session1/chapter11/tispark-intro.md
tigeriq188 Apr 5, 2020
943dcad
Update tispark-architecture.md
tigeriq188 Apr 7, 2020
d83d390
Update tispark-architecture.md
tigeriq188 Apr 7, 2020
62443d3
Update tispark-architecture.md
tigeriq188 Apr 7, 2020
ed296c0
Update tispark-architecture.md
tigeriq188 Apr 7, 2020
902ba90
Update session1/chapter11/tispark-architecture.md
tigeriq188 Apr 7, 2020
75293fe
Update tispark-intro.md
tigeriq188 Apr 7, 2020
59c5d35
Update tispark-intro.md
tigeriq188 Apr 7, 2020
4153305
Update tispark-architecture.md
tigeriq188 Apr 7, 2020
9793032
Update tispark-architecture.md
tigeriq188 Apr 7, 2020
c4bcdc5
Update tispark-architecture.md
tigeriq188 Apr 7, 2020
dc6fbd0
Update tispark-architecture.md
tigeriq188 Apr 7, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions session1/chapter11/tispark-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,17 @@ TiSpark 是将 Spark SQL 直接运行在分布式存储引擎 TiKV 上的 OLAP
* 将 TiKV 数据包解码并转化为为 Spark SQL 的行格式

### 11.1.2 富 TiKV Java Client
如上架构所示 TiSpark 需要从 TiKV 中获取表结构信息和底层 KV Pair 信息,那么 TiSpark 如何与 TiKV 通信获取这些信息呢? 这里就需要 TiKV Java Client ,通过 gRPC 与 TiKV Server 通信调用 TiKV API 。
如上架构所示 TiSpark 需要从 TiKV 中获取表结构信息和底层 Key-Value Pair 信息,那么 TiSpark 如何与 TiKV 通信获取这些信息呢? 这里就需要 TiKV Java Client ,通过 gRPC 与 TiKV Server 通信调用 TiKV API 。

* 解析 TiKV Table Schema 将 TiKV 中的 Schema 信息转化为 Spark SQL 认识的 Schema
* 解析 TiKV 的类型系统
* 从 TiKV 中获取的数据是 KV Pair 需要,编码解码模块负责将 KV Pair 转化为 Spark SQL 可以使用的数据。这里的编解码逻辑和 TiDB 编解码逻辑一致。
* 协处理器支持,可以谓词,索引,键值域处理计算下推到 TiKV 侧,减少数据传输过程更能利用 TiKV 的分布式计算能力。在调用协处理的时候也依赖上面类型系统和编码系统,用于构造协处理器调用参数。
* 为了更加精确选择查询计划,提高 SQL 运行效率, TiSpark 中 Java TiKV Client 利用了 TiDB 的统计信息实现了更合理的基于代价的估算
* 从 TiKV 中获取的数据是 Key-Value Pair ,需要编码和解码模块负责将 Key-Value Pair 转化为 Spark SQL 可以使用的数据。这里的编解码逻辑和 TiDB 编解码逻辑一致。

* 协处理器支持,可以把谓词,索引,键值域处理计算下推到 TiKV 侧,减少数据传输过程,更能利用 TiKV 的分布式计算能力。在调用协处理的时候也依赖上面类型系统和编码系统,用于构造协处理器调用参数。
* 为了更加精确选择查询计划,提高 SQL 运行效率, TiSpark 中 Java TiKV Client 利用了 TiDB 的统计信息实现了更合理的基于代价的估算。

### 11.1.3 打通 TiKV 和 TiSpark
通过富 Java TiKV Client 可以完成 TiSpark 与 TiKV 通信,获取 TiKV 的相关数据,如何将 TiKV 的数据注入到 Spark 中完成 Spark 程序分布式计算呢? 答案是通过修改 Spark Plan 可以完成。Spark 内置了扩展性接口,通过扩展 SparkSessionExtensions 类 Spark 可以实现用户自定义 SQL Plan语法支持以及元数据解析等。具体可以参见下图 Spark 官网 API 说明。
通过富 Java TiKV Client 可以完成 TiSpark 与 TiKV 通信,获取 TiKV 的相关数据,如何将 TiKV 的数据注入到 Spark 中完成 Spark 程序分布式计算呢? 答案是通过修改 Spark Plan 可以完成。Spark 内置了扩展性接口,通过扩展 SparkSessionExtensions 类 Spark 可以实现用户自定义 SQL Plan语法支持以及元数据解析等。具体可以参见下图 Spark 官网 API 说明。

![图片](/res/session1/chapter11/spark-extension.png)

Expand All @@ -44,14 +45,14 @@ spark.sql.extensions org.apache.spark.sql.TiExtensions

![图片](/res/session1/chapter11/tiextension.png)

原生 Spark SQL 执行计划如下图左边所示,一个 Spark SQL 开始运行,通过 Catalyst 解析器被解析为逻辑执行计划,在优化器中生成物理执行计划,最后通过 DataSource 的 API 获取数据。 TiSpark 修改 Spark Plan 之后 SQL 执行过程如下图右边所示。将 SQL 优化器和物理执行计划改写为与 TiKV 相关的交互,在物理执行计划中从 TiKV 获取表结构、数据和索引等信息。改写之后 Spark 看到的接口不变,但是底层实现变成了从 TiKV 交互,既保证了与原来 Spark 程序的兼容又完成 TiKV 数据注入。
原生 Spark SQL 执行计划如下图左边所示,一个 Spark SQL 开始运行,通过 Catalyst 解析器被解析为逻辑执行计划,在优化器中生成物理执行计划,最后通过 DataSource 的 API 获取数据。 TiSpark 修改 Spark Plan 之后的 SQL 执行过程如下图右边所示。将 SQL 优化器和物理执行计划改写为与 TiKV 相关的交互,在物理执行计划中从 TiKV 获取表结构、数据和索引等信息。改写之后 Spark 看到的接口不变,但是底层实现变成了与 TiKV 交互,既保证了与原来 Spark 程序的兼容又完成 TiKV 数据注入。

![图片](/res/session1/chapter11/process.png)

### 11.1.4 聚簇索引
上面 Spark SQL 架构比较抽象,具体来看一个例子:

Spark SQL 运行如下 SQL ,其中 student 表是 TiDB 中的表,在 studentID 列上有聚簇索引, 在 school 列上的非聚簇索引。聚簇索引会将索引和数据放在一起。
Spark SQL 运行如下 SQL ,其中 student 表是 TiDB 中的表,在 studentID 列上有聚簇索引, 在 school 列上有非聚簇索引。聚簇索引会将索引和数据放在一起。

SELECT class, avg(score) FROM student

Expand All @@ -61,7 +62,7 @@ GROUP BY class ;

![图片](/res/session1/chapter11/filter.png)

在上图中 studentID 是一个聚簇索引, TiKV Region 中会包含聚簇索引的范围,比如上图中 Region 2 的 studentId 范围是 [5000 - 10000) , Region 3 的 studentID 范围是 [10000 - 15000) 。在 SQL 运行时聚簇索引会转化为对 TiKV 的范围查询,现在需求查找数据范围在 8000 到 10100 ,TiSpark 会将对于的请求发送到 Region 2 和 Region 3 做范围查找。TiSpark 会在 Spark Executor 端将 TiKV 支持的谓词发送给 TiKV 协处理器计算,并将 TiKV 计算之后的结果进行汇总和再计算。 对于 TiKV 不支持的谓词部分会留在 Spark 中计算得到最终 SQL 运行结果。
在上图中 studentID 是一个聚簇索引, TiKV Region 中会包含聚簇索引的范围,比如上图中 Region 2 的 studentId 范围是 [5000 - 10000) , Region 3 的 studentID 范围是 [10000 - 15000) 。在 SQL 运行时聚簇索引会转化为对 TiKV 的范围查询,现在要查找范围在 8000 到 10100 的数据 ,TiSpark 会将对应的请求发送到 Region 2 和 Region 3 做范围查找。TiSpark 会在 Spark Executor 端将 TiKV 支持的谓词发送给 TiKV 协处理器计算,并将 TiKV 计算之后的结果进行汇总和再计算。 对于 TiKV 不支持的谓词部分会留在 Spark 中进行计算,从而得到最终 SQL 运行结果。

### 11.1.5 非聚簇索引处理
非聚簇索引被编码为键值对,键是按照索引列顺序排序的数据,值是指向表主数据的 Row ID 。
Expand All @@ -71,7 +72,7 @@ GROUP BY class ;
* 首先根据谓词对索引表进行扫表,逻辑类同之前对聚簇索引的读取。
* 根据 Row ID 和所属 Region 分发整理数据
* 在每个 Spark Executor 排序这些 Row ID 并尽可能整合成更大的值域段
* 针对所查询的表进行编码并并发发送请求
* 针对所查询的表进行编码,同时并发发送请求

例如下图中扫描 school 的非聚簇索引表数据,得到 1,2,3,4,5,7,8,10,88 的 Row ID ,在 Spark Executor 端对这些 Row ID 排序,再根据 Row ID 对 student 主表进行范围扫描,再将 TiKV 主表返回数据在 Spark 中再计算得到最终结果。

Expand All @@ -83,17 +84,16 @@ TiStrategy 负责改写 TiSpark 的物理执行计划,假设 Spark SQL 中包
![图片](/res/session1/chapter11/agg.png)

### 11.1.7 分布式大数据写入
最初 TiSpark 只能通过 TiDB JDBC 的方式将数据写入到 TiDB ,这存在可扩展性问题,将 TiSpark 直接写入 TiKV 则可以解决此问题。在 Spark 中数据一般是以 DataFrame 的形式存在, TiSpark 写入过程中可以将 DataFrame 的数据转化为 TiKV 认识的格式,并通过 TiKV Java Client 将数据写入 TiKV。
最初 TiSpark 只能通过 TiDB JDBC 的方式将数据写入到 TiDB ,这存在可扩展性问题。通过 TiSpark 直接写入 TiKV 则可以解决此问题。在 Spark 中数据一般是以 DataFrame 的形式存在, TiSpark 写入过程中可以将 DataFrame 的数据转化为 TiKV 认识的格式,并通过 TiKV Java Client 将数据写入 TiKV。

* 根据 DataFrame 中数据进行 Region 预切分和分配
* TiKV 数据写入需要支持分布式事务, TiKV 采用 Percolator 协议进行事务操作,操作过程如下:
* 在 Spark Driver 端开始写数据时申请 TiKV 中主数据预写,对此条数据加锁。
* 在 Spark Executor 端将 DataFrame 转化为 TiKV 的 KV Pair 格式,并调用 gRPC 进行次数据预写,将 DataFrame 数据存入到 TiKV , 此过程如果存在写入冲突可以选择报错或者覆盖写入。
* 在 Spark Executor 端将 DataFrame 转化为 TiKV 的 Key-Value Pair 格式,并调用 gRPC 进行次数据预写,将 DataFrame 数据存入到 TiKV , 此过程如果存在写入冲突可以选择报错或者覆盖写入。
* 在 Spark Driver 端等待 Spark Executor 预写成功,再将主数据提交。 Percolator 提交成功取决于主数据提交状态。
* 在 Spark Excutor 端提交次数据。到此完成了所有两阶段事务提交。

### 11.1.8 总结
TiSpark 实现了富 TiKV Java Client ,并通过 Spark 内置扩展接口改写 Spark Plan ,将 TiKV 的表结构和数据集成到 Spark 中。 非常巧妙的将 TiKV 体系和现有大数据体系融合起来。再通过分析 TiSpark 对聚簇和非聚簇索引的处理,以及协处理器在其中的作用,加深了对 TiSpark 与 TiKV 交互的理解。 最后分析 TiSpark 分布式写入 TiKV ,完成了 TiSpark 对 TiKV 读和写的总体理解。



13 changes: 13 additions & 0 deletions session1/chapter11/tispark-intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## 第11章 TiSpark 简介与实战

TiSpark 是 PingCAP 为解决用户复杂 OLAP 需求而推出的产品。它能够让 Spark SQL 直接运行在分布式存储引擎 TiKV 上,和 TiDB 一起为用户提供了一站式解决 HTAP (Hybrid Transactional/Analytical Processing) 解决方案。

在这部分内容中,首先向大家介绍 TiSpark 的总体架构和基本原理,然后介绍 TiSpark 的部署和使用方法,接下来向大家介绍 TiSpark 如何运行在 PingCAP 为复杂分析型场景而研发的列式存储引擎 TiFlash 的基本知识,最后介绍 TiSpark 融合到已有大数据生态体系的方法。
tigeriq188 marked this conversation as resolved.
Show resolved Hide resolved


## 目录

- [11.1 TiSpark 架构与原理](tispark-architecture.md)
- [11.2 TiSpark 的使用](tispark-in-action.md)
- [11.3 TiSpark on TiFlash](tispark-on-tiflash.md)
- [11.4 TiSpark 结合大数据体系](tispark-on-bigdata.md)
15 changes: 8 additions & 7 deletions session1/chapter4/scheduling-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@
任何一个复杂的系统,用户感知到的都只是冰山一角,数据库也不例外。前两篇文章介绍了 TiKV、TiDB 的基本概念以及一些核心功能的实现原理,这两个组件一个负责 KV 存储,一个负责 SQL 引擎,都是大家看得见的东西。在这两个组件的后面,还有一个叫做 PD(Placement Driver)的组件,虽然不直接和业务接触,但是这个组件是整个集群的核心,负责全局元信息的存储以及 TiKV 集群负载均衡调度。

## 4.1 调度概述
本篇文章介绍一下这个神秘的模块。这部分比较复杂,很多东西大家平时不会想到,也很少在其他文章中见到类似的东西的描述。我们还是按照前两篇的思路,先讲我们需要什么样的功能,再讲我们如何实现,大家带着需求去看实现,会更容易的理解我们做这些设计时背后的考量。
本章介绍一下这个神秘的模块。这部分比较复杂,很多东西大家平时不会想到,也很少在其他文章中见到类似东西的描述。我们还是按照前两篇的思路,先讲我们需要什么样的功能,再讲我们如何实现,大家带着需求去看实现,会更容易的理解我们做这些设计时背后的考量。

### 4.1.1 为什么要进行调度
在第一篇文章提到的一些信息,TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为单位进行复制和管理,每个 Region 会有多个 Replica(副本),这些 Replica 会分布在不同的 TiKV 节点上,其中 Leader 负责读/写,Follower 负责同步 Leader 发来的 raft log。了解了这些信息后,请思考下面这些问题:
TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为单位进行复制和管理,每个 Region 会有多个 Replica(副本),这些 Replica 会分布在不同的 TiKV 节点上,其中 Leader 负责读/写,Follower 负责同步 Leader 发来的 raft log。了解了这些信息后,请思考下面这些问题:

* 如何保证同一个 Region 的多个 Replica 分布在不同的节点上?更进一步,如果在一台机器上启动多个 TiKV 实例,会有什么问题?
* TiKV 集群进行跨机房部署用于容灾的时候,如何保证一个机房掉线,不会丢失 Raft Group 的多个 Replica?
* 添加一个节点进入 TiKV 集群之后,如何将集群中其他节点上的数据搬过来?
* 当一个节点掉线时,会出现什么问题?整个集群需要做什么事情?如果节点只是短暂掉线(重启服务),那么如何处理?如果节点是长时间掉线(磁盘故障,数据全部丢失),需要如何处理?假设集群需要每个 Raft Group 有 N 个副本,那么对于单个 Raft Group 来说,Replica 数量可能会不够多(例如节点掉线,失去副本),也可能会 过于多(例如掉线的节点又回复正常,自动加入集群)。那么如何调节 Replica 个数?
* 当一个节点掉线时,会出现什么问题?整个集群需要做什么事情?如果节点只是短暂掉线(重启服务),那么如何处理?如果节点是长时间掉线(磁盘故障,数据全部丢失),需要如何处理?假设集群需要每个 Raft Group 有 N 个副本,那么对于单个 Raft Group 来说,Replica 数量可能会不够多(例如:节点掉线,失去副本),也可能会过于多(例如:掉线的节点又恢复正常,自动加入集群)。那么如何调节 Replica 个数?
* 读/写都是通过 Leader 进行,如果 Leader 只集中在少量节点上,会对集群有什么影响?
* 并不是所有的 Region 都被频繁的访问,可能访问热点只在少数几个 Region,这个时候我们需要做什么?
* 集群在做负载均衡的时候,往往需要搬迁数据,这种数据的迁移会不会占用大量的网络带宽、磁盘 IO 以及 CPU?进而影响在线服务?

这些问题单独拿出可能都能找到简单的解决方案,但是混杂在一起,就不太好解决。有的问题貌似只需要考虑单个 Raft Group 内部的情况,比如根据副本数量是否足够多来决定是否需要添加副本。但是实际上这个副本添加在哪里,是需要考虑全局的信息。整个系统也是在动态变化,Region 分裂、节点加入、节点失效、访问热点变化等情况会不断发生,整个调度系统也需要在动态中不断向最优状态前进,如果没有一个掌握全局信息,可以对全局进行调度,并且可以配置的组件,就很难满足这些需求。因此我们需要一个中心节点,来对系统的整体状况进行把控和调整,所以有了 PD 这个模块。
这些问题单独拿出可能都能找到简单的解决方案,但是混杂在一起,就不太好解决。有的问题貌似只需要考虑单个 Raft Group 内部的情况,比如根据副本数量是否充足来决定是否需要添加副本,但是实际上这个副本添加在哪里,是需要考虑全局信息的。同时整个系统也是在动态变化,Region 分裂、节点加入、节点失效、访问热点变化等情况会不断发生,整个调度系统也需要在动态中不断向最优状态前进,如果没有一个掌握全局信息,可以对全局进行调度,并且可以配置的组件,就很难满足这些需求。因此我们需要一个中心节点,来对系统的整体状况进行把控和调整,所以有了 PD 这个模块。

### 4.1.2 调度的需求
上面罗列了一大堆问题,我们先进行分类和整理。总体来看,问题有两大类:
Expand All @@ -31,10 +31,11 @@

* 维持整个集群的 Leader 分布均匀
* 维持每个节点的储存容量均匀
* 维持访问热点分布均匀控制 Balance 的速度,避免影响在线服务
* 管理节点状态,包括手动上线/下线节点,以及自动下线失效节点
* 维持访问热点分布均匀
* 控制负载均衡的速度,避免影响在线服务
* 管理节点状态,包括手动上线/下线节点

满足第一类需求后,整个系统将具备多副本容错、动态扩容/缩容、容忍节点掉线以及自动错误恢复的功能。满足第二类需求后,可以使得整体系统的负载更加均匀、且可以方便的管理
满足第一类需求后,整个系统将具备强大的容灾功能。满足第二类需求后,可以使得系统整体的负载更加均匀,管理更加容易方便

为了满足这些需求,首先我们需要收集足够的信息,比如每个节点的状态、每个 Raft Group 的信息、业务访问操作的统计等;其次需要设置一些策略,PD 根据这些信息以及调度的策略,制定出尽量满足前面所述需求的调度计划;最后需要一些基本的操作,来完成调度计划。

Expand Down
18 changes: 18 additions & 0 deletions session1/chapter9/tiflash-intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# 第9章 TiFlash 简介与 HTAP 实战

近年来,随着企业数字化转型的不断深入和发展,数据逐渐成为企业最重要的资产。对于每一个企业来说,都需要关注数据从产生、存储、分析到利用,并发挥其巨大价值的整个过程。此外,随着企业之间竞争的不断加剧,对数据的产生到发挥其价值的时间延迟要求越来越短。

作为存储和处理数据最重要的基础软件——数据库系统,一般可以按照负载类型分成 OLTP 型数据库和 OLAP 数据库。在一个企业中,这两种类型的数据库通常是并存的,分别支撑这两种负载类型的应用系统。目前,很多企业的这两种类型的系统之间是通过较为复杂的 ETL 过程“打通的”,数据在时效性上具有比较大的 T+N 延时,这越来越难以满足企业在数据处理和分析方面对时效性的要求。


近几年,HTAP 是比较热的一个概念,它是最有希望解决目前问题的方法。顾名思义, HTAP 是混合 OLTP 和 OLAP 业务,具备同时解决这种两种问题能力的系统。2014 年 Garnter 公司给出了严格的定义:混合事务/分析处理 (HTAP) 是一种新兴的应用体系结构,它打破了事务处理和分析之间的 “墙” 。它支持更多的”信息分析“和 “实时业务” 的决策。


TiDB 是一个具有优异交易处理能力的分布式 NewSQL 产品,同时也具备了良好的分析能力,又是一款优秀的 HTAP 数据数据库产品。在这部分内容中,首先向大家介绍 TiDB HTAP 的主要特点,然后介绍其实现 HTAP 能力的关键技术之一的 TiFlash 列式存储引擎的架构和基本原理,最后向大家介绍 TiFlash 如何使用。


## 目录

- [9.1 TiDB HTAP 的特点](tidb-htap.md)
- [9.2 TiFlash 架构与原理](tiflash-architecture.md)
- [9.3 TiFlash 的使用](tiflash-in-action.md)