PCTA 认证 -101 课程学习笔记
作者: evanyou26 原文来源:https://tidb.net/blog/945b7eed
近期备考 PCTA 认证过程中的学习笔记,主要是基于 101 课程记录的,目前考试已完成,分享出来供参考。
一、TiDB 数据库架构概述
1.1 核心功能
水平扩容或者缩融
金融级高可用
实时 HTAP
云原生的分布式数据库
兼容 MySQL 5.7 协议
1.2 TiDB Server
核心作用
处理客户端的连接
SQL 语句的解析和编译
关系型数据与 KV 的转化
SQL 语句的执行
执行 online DDL
垃圾回收 (GC):tidb 的修改删除都是新增 KV 键值对,不会更改原有数据,TiDB Server 会定期将存储在 TiKV 中的无效数据清理回收。
热点小表缓存 V6.0
1.3 TiKV
数据持久化:每个节点存在 2 个 rocksdb 存储数据
副本的强一致性和高可用性:基于 Raft 协议
MVCC (多版本并发控制)
分布式事务支持
Coprocessor(算子下推):每个节点可以做一定的计算工作,如过滤、投影、聚合等。
1.4 Placement Driver
整个集群 TiKV 的元数据存储
分配全局 ID 和事务 ID
生成全局时间戳 TSO
收集集群信息进行调度
提供 TiDB Dashboard 服务
1.5 TiFlash
异步复制
一致性
列式存储提供分析查询效率
业务隔离
智能选择
二、TiDB Server
2.1 架构
SQL 语句的解析编译:Protocol Layer、Parse、Compile 生成 sql 的执行计划 ,交给 ExecutorProtocol Layer:处理客户端的连接 Parse+Compile:解析编译
分批的执行 sql 的执行计划:Executor、DistSQL、KV
事务的相关 SQL 执行:Transaction、KV
与 PD、TiKV 的交互:PD Client、TiKV Client
Online DDL:schema load、worker、start job
memBuffer:缓存读取出来的数据、元数据、登录认证信息等
2.2 作用、进程
2.2.1 SQL 语句的解析和编译
Parse:通过词法分析、语法分析,将 sql 解析成抽象语法树 (AST),传递给 Compile 模块 Compile:
合法性验证:语句相关的表是否存在等等
逻辑优化:依据关系型代数的等价规则做一些逻辑变换,如列裁剪将不需要的列去掉、最大最小消除、投影消除、算子下推、子查询、外连接变内连接等等一系列在 sql 层面可以做的语句优化
物理优化:根据逻辑优化的结果,考虑数据分布、大小决定用哪个算子,即结合统计信息,决定走索引还是全表扫描,走索引的话走哪个索引
2.2.2 关系型数据与 KV 的转化
TiDb 中的数据最终是存储成 key-value 的键值对。这里讲的是聚簇表,key 以表号 + 主键的形式组成 key。(非聚簇表的 key 没有主键,是自动生成的 rowid)region:key value 的数据集合组成 region,默认 96M,当达到 144M 时,会 split 分裂成 2 个 region。(region 是存储在 TiKV 中的)
2.2.3 SQL 读写相关模块
复杂的 SQL、嵌套查询等等,Executor 会将其交给 DistSQL 转化成单表的操作组合,再发给 TiKV。
点查会走 KV 的模块,如简单的单行请求。
存在事务的,会先经过 Transaction 后再到 KV;Transaction 会在开始时和提交时从 PD 中获取 TSO 时间戳。
2.2.4 在线 DDL 相关模块
集群中存在多个 TiDB Server,都可以接收 DDL 操作请求,但同一时间只会有 1 个 TiDB Server(Owner) 执行 DDL 操作。
start job:接收用户发起的 DDL 操作语句,将其放到 TiKV 中的 job 队列中
worker:负责执行 DDL 操作,由 Owner 角色的 TiDB Server 中的 worker 去取 job queue 的第一个 job,然后执行;执行结束后放入到 history queue 中。
同一时间只有 1 个 owner,存在一个任期,到达任期后会重新发起选举决定新的 owner。
schema load:成为 owner 的 tidb server,会将最新的表 schema 的信息同步到其内部的缓存中,好根据这些信息去执行 job queue。
job 放在 tikv 是为了持久化。
2.2.5 GC 机制与相关模块
TiDB Server 的 GC 是清理历史的版本数据。
由 GC leader 进行清理。
基于 safe point 进行清理:如 safe point 为 10:00am,在这之后的历史版本数据还存在,之前的会被清理。
GC lift time:默认为 10min,即 10 分钟内的历史版本数据会保留。
2.3 缓存
2.3.1 缓存组成
SQL 结果:数据结果可能分散在多个 Tikv 节点中,需要有地方来汇聚数据;事务数据的缓存之类的。
线程缓存
元数据,统计信息
2.3.2 缓存管理
tidb_mem_quota_query:控制每一个 SQL/ 查询默认使用的缓存存储量
oom-action:决定缓存超量时,返回 error 还是记录日志等行为。
2.3.3 热点小表缓存
为了解决频繁从读取 tikv 小表数据,将数据缓存到 tidb server 的 cache table 中
表的数据量不大:
只读表或者修改不频繁的表
表的访问很频繁
设置租约,如 5s,租约到期前从 cache table 中直接读取,到期后再次从 tikv 中读取并缓存到 cache 中;如果修改表,租约到期前会阻塞修改操作,待租约到期后再执行修改,读写直接到 TIKV 节点上执行。
设置为热点小表的表不支持 DDL,需要先关闭后再进行 DDL 操作
租约到期后的一次读取会比平时慢一点
三、TiKV
架构和作用
数据持久化
分布式一致性
MVCC
分布式事务
Coprocessor
3.1 持久化
3.1.1 RocksDB
3.1.2 RocksDB:写入
将数据写入磁盘的 WAL 的日志文件中,保障数据的原子性。
会先写到操作系统的缓存中,再批量写入到 WAL 日志文件中,有丢失概率的风险。
sync-log:设置为 true 时,会直接写到 WAL 日志文件中,会损失一部分性能 (大概 30%),但更安全有保障,官方推荐是开启。
将数据写入到内存中,积累到一定数据后一次性写入到磁盘。
MemTable:内存的数据,保存落盘前的数据,通过跳跃表、搜索树来保障数据的有序性,追加到一定的数据量(基于 write buffer size 参数),就将其数据转存到 immutable MemTable,然后重新开辟一个 MemTable。
immutable MemTable:不能改的缓存数据,此节点存在的目的是为了防止写入的 IO 等待,immutable 写入磁盘时可能产生 IO 等待,这样不影响 MemTable 的写入,防止写阻塞。有 1 个 immutable 就会写入到磁盘,如果写入数据太多,可能产生多个,默认达到 5 个时会触发 tidb 的流控(基于 write stall)。
Level 0:immutable MemTable 的一个复刻,默认达到 4 个后,就会向下一层压缩排序存储,这个过程叫做 compaction。
Level1 以后:文件会切分成一个个的 ssd table 文件 (SST 文件),以 Key-Value 形势按序存储。
每一层达到最大容量后,compaction 往下一层存储
文件查询:文件都是有序的,通过二分查找法查询
写入操作:修改、新增都是直接添加对应 key 进入 memtable 即可,基于二分查找最终存储到对应 Level 层级文件的地方即可。写入非常友好。
3.1.3 RocksDB 查询
Block Cache:将最近、最常用的数据缓存在此处。
读取顺序:按下图,Block Cache 中没有,依次在 MemTable 中,一直往下查询。
单个文件:存在 min、max 值,基于二分查找法快速定位。
bloom filter:如果判定某个 key 在该文件中,它可能在;判定不在,则一定不在。
3.1.4 RocksDB:Column Families(列簇)
可以分别存取不同表的数据,实现数据分片。
示例:Write(cf1,id,name,age,xxx),cf1 为指定的列簇,id 为 key,后面为值。
未指定列簇时,有一个默认的列簇 default。
WAL 文件是共享的,不存在列簇的区分。
3.2 分布式事务
3.2.1 事务流程
beigin:start timestamp=100。从 PD 中获取开始的 TSO
prewrite:修改数据 + 锁信息。锁信息如果只写在 tikv 节点的内存中,其他节点感知不到,只有最后 commit 时才知道,这叫做乐观事务锁(tidb 早期版本是只实现的乐观锁);锁信息提前写入到 tikv 节点中,其他节点能感知到,这叫悲观事务锁。修改数据 + 锁信息:通过 3 个列簇存储,Default、Lock、Write;其中 Default 中的 key 包含数据 key+TSO;Lock 存储锁信息,注意一个事务中操作如果存在多行操作,只会给第一行加一个主锁,其他行均依附于该主锁。下图示例中 3 代表数据 keyID,W 代表为写锁,100 为事务的开始时间戳
commit:commit timestamp=110。从 PD 中获取事务结束的 TSO,在 write 列簇中写入,如下图所示包含 keyid+ 提交的时间戳,以及对应事务开始的时间戳。清理锁信息,在 Lock 中删除对应的锁。注意删除并非直接删除数据,而是新增一个 D 的锁数据,代表其为删除。
其他人想要读取 key 为 3 的值时,先到 Write 列簇中最近一次修改是什么时间,得知最后一次如上图所示为 3+100 时间戳,就能在 Default 中找到 3_100 的值为 Frank;如果在事务提交前读取,在 Write 中没找到信息,Lock 中存在 3_100 的锁信息,此时不能读取 3_100 的值。其他情况
Write 列:当用户写入了一行数据时,如果该行数据长度小于 255 字节,那么会被存储在 write 列中,否则的话该行数据会被存入到 default 列中。
Default 列:用于存储超过 255 字节长度的数据。
3.2.2 分布式事务
基本流程与单节点事务流程一致,下图示例中 key1 和 2 分别存在 2 个节点中。
第一行数据 1 的锁为主锁,标识为 pk;第二行数据非主锁,依附于主锁,标识为 @1。
commit 时流程一致,分 3 步先获取提交的 TSO,然后在 write 中写入,再删除锁。
由于分布式是多节点,加入 commit 时,node1 节点提交成功,此时 note2 宕机导致提交失败,这时读取 node1 的 key1 数据能正常读取结果;node2 恢复后读取 2 时未在 write 中找到 2_110 的提交信息,但通过查锁发现存在 W 的 @1 的锁信息,再查 node1 的队友主锁信息,发现已被删除,这里可以知道之前是因为宕机等原因没提交成功,这时恢复完善 write 和删除 @1 锁信息,就可以正常读取。(解决了分布式事务的原子性问题)
3.2.3 MVCC
解决事务过程中的读阻塞问题。
TiKV 不管修改还是删除一个值,都是采取的新增数据的模式。
下图中 TS0=120 时,1 的值为 Jack,2 的值为 Candy,4 的值为 Tony;如果没有 MVCC,1、4 都不能读取。![[Pasted image 20250910075448.png]]TSO=120 时操作
读取 1 的值:在 Write 中找到 1 的最近一次的提交记录为 1_110,拿着 1_100 读取 Default 中的值为 Jack
尝试写 1 的值:在 Write 中找到 1 的最近一次的提交记录为 1_110,但在 Lock 中找到了 1 时间戳为 115 的锁,此时阻塞不能修改。
尝试写 2 的值:在 Write 中找到 1 的最近一次的提交记录为 1_110,在 Lock 中也没找到 2 的锁,此时可修改。
读取 4 的值:在 Write 中找到 4 的最近一次的提交记录为 4_90,拿着 4_80 读取 Default 中的值为 Tony。
尝试写 4 的值:在 Write 中找到 4 的最近一次的提交记录为 4_90,但在 Lock 中找到了 4 有个依附于 @1 的主锁,再查主锁发现还锁着,此时阻塞不能修改。
3.3 Raft
3.3.1 部分基本概念
region:数据存储的逻辑单元,tikv 中默认为 3 副本,不同节点中同一数据的 region 组成一个 raft group。
region 里面的 key 存储是有序的,一个 region 的默认大小为 96MB,超过 144MB 时将分裂成 2 个 region
region 是左闭右开的连接组别,例如 region1 为[1,1000),region2 为[1000,1999)
leader:同一个 raft group 中只有 1 个 leader,负责读写,并将数据副本以日志的方式传递给 follower。
follower:被管理者,只会对其他的服务作出响应,接收 leader 的日志。如果长时间没收到 leader 的反馈,将会变成 candidate,投票以选举出新的 leader。
3.3.2 Raft 日志复制
步骤
propose:客户端将写入信息发送给 TiKV 节点(对应 region 的 leader 节点)
append:leader 接收到写入请求,将内容写入到 raft 日志中 (格式:reaginId_ 序号,log{PUT key=xx,name=xx},存储在 leader 当前节点的 raftDb 中,用来专门存放 raft log 的 Db)
replicate:将日志内容传递给 follower,
committed:当多数的节点返回 append 成功消息后,视为 committed 成功。(此 committed 不是指 sql 应用中的 committed,仅仅指 raft log 的 committed)
apply:将 raft log 写入到 rocksdb kv 中,此时数据真正存到 KV 中,可以 SQL 读取。
3.3.3 Raft Leader 选举
term:一段时期的意思,raft 共识协议将时间分成的一小段一小段的单位,代表一段稳定的关系,不是固定的长度。用一个递增的数据来标识。
election timeout:选举超时周期,校验集群中长时间没有 leader 将发起投票的超时时间
heartbeat time interval:心跳周期,接收到 leader 发送心跳的计时器,假设为 10s,正常从 0 开始计时,经过 5 秒后变成 5 后,收到 leader 发送的心跳,便重新变为 0 计时。
初始状态:最初启动时,所有 region 节点都是 follower,此时各自会等待 leader 的信息,超过 election timeout 后,会认为集群中没有 leader,哪个节点率先超过 timeout 时间后,该 region 角色由 follower 变成 candidate(term1 变成 term2),发起选举并将 term2 给其他节点,其他节点收到投票请求后对比请求的 term2 比自己的 term1 大,同意投票返回给 candidate 节点,成功转变为 leader(超过一半的投票即成功,包括自己的一票)。
进行中突然宕机:follower 在超过 interval 时长后未接收到 leader 心跳消息时,转变为 candidate 进入下一个 term,发起选举流程。
node2 恢复后变成 candidate,但会发现其他节点的 term 更高,将会转成 follower。
初始阶段特殊情况:初始时若刚好存在 2 个以上的节点同时 timeout 并发起选举,这时就会失败,系统会重复发起多次选举,直到选举成功。
tidb 加入了一个 random 变数解决该问题,即 election timeout 设置一个区间值,如 (100ms-300ms),这样每次会是一个随机 timeout 值,就能很高概率的避免同时选举的场景出现。
一个 ticks 是一个时间单位,对应一个 interval,即 1 秒。
raft-election-timeout-ticks 不能小于 raft-heartbeat-ticks,tikv 中默认配置 timeout 为 hertbeat 的 2 倍以上。
3.4 读写与 Coprocessor
这里的写入暂时忽略 MVCC、Transaction 的过程,只关注 Raft 的写入。
3.4.1 数据的写入
PD:提供时间戳,还有写入的数据在哪一个 tikv 的那个 region 上。
raftstore pool:线程池,收到写请求转换为 raft 日志,持久化存储,发送日志给其他节点,接收其他节点的成功响应。
apply pool:线程池,将日志数据写入到 kv 中。
用于能读到的数据都是最终进入 KV 中后的。
3.4.2 数据的读取
读取时需要从 PD 获取时间戳及 key 对应的 leader 在哪个节点
读取过程中有耗时,读取时会向其他节点发心跳确保读的节点是 leader。
ReadIndex Read
读取线性一致性:在一个时间修改了数据,在之后时间读取到的一定是这个修改后的数据。
注意这里是抛开了 MVCC 机制单独来看的 Raft 层。
10:00 时用户修改了如下图所示的 1 将 tom 改为 jack,对应数据的 raft log 时间节点为 1-95。
10:05 时用户读取 key1 的值,当前时间的 raft log 的 commit 进度为 1-97,这个值记录为 ReadIndex。
10:08 时 1-95 时 key1 的值 apply 成功,存储到了 KV 中。
10:09 时用户读取的操作还在等,等到 ReadIndex1-97 时其对应的数据 apply 成功,此时能够保障之前的 95 一定 apply 成功,这时读取成功,保障了数据一致性。
Lease Read
确保当前的节点为 leader,会给其他节点发送心跳确认是否为 leader,针对这个过程的优化读取就是 Lease Read。
10 点时 leader 节点发送心跳成功后,在 heartbeat time interval 时间范围内,能保障其肯定为 leader。
10 点时到 election timeout 的时间段,哪怕其他节点没收到心跳,这个时间范围内也来不及重新发起选举,也能保证其还是 leader。
Follower Read
在 follower 节点中读取数据,以减轻 leader 节点的读取压力。难点在于怎么保证线性一致性。
下面的 2 张图分表为 leader 节点和 follower 节点的时间轴关系
10:00 的时候,leader 节点写入了一个数据,如图一所示,对应数据的 log 时间节点为 1-95
10:00 的时候,follower 节点如图二,跟 leader 节点 apply 进度有所区别。(不同节点也正常)
10:05 时,用户在 follower 节点进行了数据读取,此时 raft commit 的日志为 1-97,记录为 CommitIndex,这个时间戳 apply 完成时,之前的时间戳的日志一定就 apply 完成了。
10:08 时,leader 节点的数据实际写入到 KV 中
10:10 时,follower 节点的 log1-97 才被 apply,此时读取到 key 的数据,即能保障 1-95 的数据能正确读取到。
follower 节点有可能性能很快,如下图所示,1-97 的 apply 进度缩短到了 10:06,比 leader 节点时间数据 commit 的 10:08 实际存储到位还要早。
3.4.3 Coprocessor
如下图所示计算 T 的数量,T 表的数据又散落在不同的 KV 节点中,如果将数据全部汇总到 TIDB 中,网络开销和 CPU 计算负载都很高。
借助 TiKV 节点进行一些计算和过滤,将结果交给 TiDB 即为 Coprocessor,帮组做算子下推的工作。
执行物理算子,为 TiDb 计算结果,减少网络和 CPU 开销
常见的 table scan、index scan 等
分析数据的统计信息、采样
四、Placement Driver
4.1 PD 的架构与功能
PD 默认 3 个节点,其中同时只会有一个 leader 角色,通过 raft 协议来保障其高可用性。
Peer:region 的副本又叫 Peer。
PD 存储了所有 region 的分布情况,会缓存到 TiDB Server 中 TiKVClient 的 Region Cache 中,减少读取开销。
back off:region 的 leader 节点变化后会告知 tikv client 原本的已经失效,需要从 PD 中从新去载入。
4.2 TSO 的分配
TSO = physical time logical time
前面部分为物理意义的时间
后面的逻辑时间能将 1ms 分成 262144 个 TSO
TSO 是一个 int64 的整型数
4.2.1 分配过程
sql 在刚开始执行的时候会请求 TSO,事务会在开始和结束时候请求 TSO。
4、5 的节点谁先完成,谁就要先等另一方。2、4 和 3、5 是异步分开同时进行的。
每个 sql 都会请求 TSO,请求数、并发量会很大,PD Client 不会来一个就执行一次 3 操作,会一次性将一批请求一次发给 PD。这个通常是限定一个时间段,比如将 5ms 的请求一次批量发给 PD,如果 5ms 内只有一个请求,也会发出去。
4.2.2 时间窗口
解决性能问题,因为 tidb server 可能会不停的发送 TSO 请求,这个请求最终落地到 PD 分配后会存储到 PD 节点,产生 IO。
如下图所示,PD 一次分配 3 秒的 TSO,放在缓存中供使用,在队列里排队使用。
3 秒后用完了,再分配至 706,这样磁盘的 IO 是 3 秒 1 次。
这个过程中 leader 如果分配了 703-706 的 TSO,其他 follower 节点的 PD 也会同步分配 703-706。
注意这个过程中假设 leader 节点的 TSO 在缓存中分配到了 704,这时 leader 宕机了,通过选举出现了一个新的 leader 节点,这时新的 leader 节点是无法知道宕机节点缓存中实际分配到 704 的,只知道之前同步已经最大分配到了 706,会重新分配新的 TSO:706-709。
通过上一条机制实现高可用,保障 TSO 不会重复,但并不能保障 TSO 的连续性,如上诉 704-705 直接会丢失。
4.3 PD 的调度原理
信息收集
TiKV 节点周期性的向 PD 发送心跳信息,还有当前节点的存储信息、Region 信息。
生成调度 (Operator)
Balance:存储的均衡和读写的均衡
Hot Region:热点 region 太集中,将其打散放在不同的节点
Region merge:一些数据、表删了后,将数据少或空的 region 进行合并
执行调度
4.4 label 的作用
下图中 DC 代表独立的数据中心,RACK 代表机柜、TIKV 代表主机。
region1 的 3 副本中 2 个副本在一个机柜上,rack4 机柜或 DC2 一出问题就不可用了(3 副本 1 个挂掉还能用,2 个就不行了)。
region2 一旦 DC1 出问题就不可用了。
region3 每个 region 都在独立的 DC\RACK\TIKV 中,稳定性最高。
Label 的配置
TikV 节点上配置 server.labels:{xxxxxx}
PD 上配置 location-labels、isolation-level
五、SQL 执行流程
5.1 流程概要
DML 读流程概要
DML 写流程概要
DDL 流程概要
job queue:除了加索引的 DDL 操作加入到此队列
add index queue:加索引的 DDL 操作加入到此队列
history queue:执行完的 DDL 操作加入到此队列
每个 TiDB Server 节点都可以接收 DDL 请求操作
只有 owner 角色的 TiDB Server 节点中的 workers 可以实际执行 queue 队列中的 DDL 命令
owner 每隔一个周期会重新发起选举选出新的 owner,轮流做 owner
5.2 SQL 的 Parse 与 Compile
Protocol Layer:该协议层监听到客户发送的 SQL 请求,先从 PD 中获取 TSO
Parse:经过词法分析和语法分析,将 SQL 转换为 AST 语法树
Compile
preprocess:预处理阶段,检测 sql 合法性,判断是否为点查 (主键、唯一索引一类的查询)
PointGet:直接点查
optimize:优化器进行逻辑优化,物理优化,产生出执行计划给到 Executor
5.3 读取的执行
Executor 先获取表的元数据(表名、列名的一些对应关系),从 information schema 中的缓存中读取(来源于 TiKV 中);还要获取需要修改 / 处理的表对应 Key 所在的 region 和 region 所在的 TiKV,从 region Cache 中读取,来源于 PD(缓存中没有就直接从 PD 中读取)。
region 发生改变时对应的 region Cache 会过期,这个过程叫做 back off,发生后需要重新从 PD 中读取。
KV:执行点查
DistSQL:将复杂的 SQL 转换成对单表的简单查询,再下发给 TiKV。
snap shot:TiKV 收到执行请求后,会先创建一个快照对象,相当于一个时间点,查询看到的数据是这个时间点之前的。
查询请求会进入到 UnifyRead Pool 线程池。
cop task:算子下推到 TiKV 进行计算的任务,如将一些聚合结果进行计算返给 TiDB Server
root task:无法在 TiKV 中计算的,如数据分散在不同的 tikv 节点,需要各自将结果集返回给 TiDB 的内存中后,在 TiDB Server 中做表连接。
5.4 写入的执行
Transaction:两阶段提交,prewrite 和 commit,详情见 3.2.1
KV:操作 key 值,通过 TiKV Client 发到 TiKV 中
Scheduler:协调事务并发写入的冲突,并将收到的修改操作向下写入。收到冲突的并发请求时 (修改同一个 Key),用 latch 来管理冲突,拿到 latch 的可以向下写入,没拿到的需要等待。
Raftstore:将写请求转换为 raft log,持久化到本地,并向其他副本发送数据。
Apply:将 raft log 应用到 raocksdb kv 中
5.5 DDL 的执行
start job:接收 DDL 语句
workers:执行 DDL 语句,仅 owner 可以执行。
schema load:为 owner 节点提供最新的表的元数据结构信息。
start job 接收到 DDL 语句时,如果当前节点为 owner,直接就给到 workers 执行;反之给到 job queue/add index queue 的队列中持久化。
owner 节点的 workers 会定期的查看 TiKV 中的 job 队列,有 job 就去执行。
owner 由 PD 节点控制,进行轮询。
六、HTAP
6.1 HTAP 概述
6.1.1 基本介绍
通过 ETL 转换成 OLAP,往往存在延迟,如 T+1 后才能查看结果。
事实上目前做的项目来说,很多场景都是按此方式去处理的,业务数据量巨大,产生的报表动态查询结果就会很慢,常用的做法就是进行转换成对应的报表结果,数据非及时。
HTAP 架构
TiFlash 以第三种角色 Learner 加入到存储集群中,不参与投票,只是进行异步复制。
TiDB 的 HTAP 特性
行列混合
列存(TiFlash)支持基于主键的实时更新
TiFlash 作为列存副本
OLTP 与 OLAP 业务隔离
智能选择(CBO 自动或者人工选择)
MPP 架构
6.1.2 MPP 架构
TiDB Server 作为协调者,会把每一个 TiFlash 列存的 Region 会在 TiFlash 各个节点中去做交换,让表连接只发生在一个 TiFlash 中。
每一个 TiFlash 都负责过滤、数据交换、表连接、聚合等等计算的节点,每个 TiFlash 都是一个 MPP Worker,驱动着各个节点并行的做计算。
如果某个 TiFlash 节点宕机,会导致 MPP 计算终结。
join 只支持等值连接
实例讲解
执行了 order 和 product 的计数联查
order、product 的表数据分布如下图 1 所示
过滤:将每个节点的 order、product 数据按查询条件的范围进行过滤,查询出结果放到内存中。
数据交换:通过 hash 函数将 order、product 值相等的数据交换到同一个节点中
Join:各个节点并行 join 查询
数据交换:再基于 state 取 hash 函数运算,进行数据交换将相等的数据放置到同一个节点
聚合:各个节点聚合,得出结果
6.1.3 运用场景
传统的流式计算场景:涉及的组件、库众多
TiDb 的流式计算场景
6.2 TiFlash
6.2.1 TiFlash 架构
TiFlash 只接收 TiKV 复制的日志,不参与投票,对原本 TiKV 的性能影响很小。
如果宕机重新从 TiKV 中同步数据副本过滤即可,对线上业务影响很小,具备业务隔离性。
TiFlash 无法直接写数据,都是通过 TiKV 异步复制数据过来写入的。
TiFlash 读取是一致的,如 TiKV 中 10:00 写入的数据,10:00 之后从 TIFlash 能读取到这个写入的数据。
TIFlash 的 QPS 一般不会很高,小于 50。
6.2.2 主要功能
异步复制
一致性读取
引擎智能选择
计算加速
6.2.2.1 异步复制
接收从 Leader 节点来的异步复制的日志数据
TiFlash 是否写入成功不需要参与 TiKV Raft 复制的 commit 反馈
6.2.2.2 一致性读取
T0 时刻从客户端写入 2 行数据,key1=100 和 key999=7,正好在不同的 region 中,对应的 raft log 的 idx 分别为 101、22。
此时 TiFlash 第一个 region 的 idx 写入到 95,第二个的 idx 写入到 18。因为异步复制,当前没数据也正常。
T1 时刻客户端向 TiFlash 读取 key1 和 key999 的值。
此时 TiFlash 的 idx 分别到了 108 和 20;tikv 的 idx 当前分别为 120 和 29。
这时 key1 的值已经在 tiflash 中了,key2 的值还没有,而且也没发保障当前 2 个 region 在 tiflash 中都存储了之前写入的数据,这时 tiFlash 需要去询问 TiKV 当前的 idx
在 Tiflash 询问 idx 前的,T2 时刻这时客户端又将 key1 的值写入为 200,此时当前的 TiKV 的 idx 为 122
T3 时刻 tiflash 询问了 tikv 节点,从 tikv 中获取了当前 tikv 的 idx,分别为 125 和 31,记录为 Wait idx。
该请求操作非常轻量。
此时 TiKV 就以这 2 个 Wait idx 来等,等到后就能保障之前的写入数据一定能进入到 TiFlash 中。
T4 时刻 tiflash 黄色 region 等到了 31idx 写入,此时 key999 能读取到 7 了
T5 时刻 tilflash 绿色 region 等到了 125,去读取 key1 发现有 2 个版本,分别对应 idx101 和 122
由于该读取请求时在 T1 请求的,按照快照隔离级别只能读取到 T1 之前写入的数据,此时读到的数据为 100
6.2.2.3 智能选择
可以同时使用 TiKV 和 TiFlash,
下面 product 的 pid 和 batch_id 走 TiKV 的索引扫,
sales 没任何过滤条件,求的平均值,走 TiFlash 的表扫
七、TiDB 6.0 新特性
7.1 Placement Rules in SQL
之前的痛点
跨地域部署的集群,无法本地访问
无法根据业务隔离资源
难以按照业务等级配置资源和副本数
有了之后
管地域部署的集群,支持本地访问
根据业务隔离资源
按照业务等级配置资源和副本数
使用步骤
应用
7.2 小表缓存
减少高频小表的对 tikv 的 IO 读取
sql 操作:alter table users cache;
7.3 内存悲观锁
之前的内存锁是乐观锁
存储在 TIKV 中持久化的为悲观锁
内存悲观锁
性能提升
leader 节点在事务过程中宕机,会出现锁丢失的情况,tidb 有机制保障其会回滚,也就是事务只是会失败。
如果能接受上一条事务发生小概率的失败场景,就可以开启内存悲观锁。
7.4 Top SQL
7.5 TiDB Enterprise Manager (TiEM)
八、TiDB Cloud
8.1 为什么选择 TiDB
作为云原生数据库的好处
分布式 SQL 数据库 - 多租户
混合工作负载 - 在同一个数据库中(HTAP)
事务型:基于行的数据
分析性:基于列的数据
弹性比例
缩小 - 减少节点
横向扩展 - 添加节点
基于 Raft 的高可用性
每个数据段在 3 个可用区进行复制
多租户
TiDB 架构
8.2 什么是 TiDB Cloud
VPC:虚拟专有网络
TiDB Cloud Central Service
提供计费、报警、元数据存储、Dashboard 等功能,对外提供服务
DeveloperTier 与 Dedicated Tier
版权声明: 本文为 InfoQ 作者【TiDB 社区干货传送门】的原创文章。
原文链接:【http://xie.infoq.cn/article/45cefd932688943dcb524e08c】。文章转载请联系作者。







评论