写点什么

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 架构

  1. SQL 语句的解析编译:Protocol Layer、Parse、Compile 生成 sql 的执行计划 ,交给 ExecutorProtocol Layer:处理客户端的连接 Parse+Compile:解析编译

  2. 分批的执行 sql 的执行计划:Executor、DistSQL、KV

  3. 事务的相关 SQL 执行:Transaction、KV

  4. 与 PD、TiKV 的交互:PD Client、TiKV Client

  5. Online DDL:schema load、worker、start job

  6. 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 事务流程

  1. beigin:start timestamp=100。从 PD 中获取开始的 TSO

  2. prewrite:修改数据 + 锁信息。锁信息如果只写在 tikv 节点的内存中,其他节点感知不到,只有最后 commit 时才知道,这叫做乐观事务锁(tidb 早期版本是只实现的乐观锁);锁信息提前写入到 tikv 节点中,其他节点能感知到,这叫悲观事务锁。修改数据 + 锁信息:通过 3 个列簇存储,Default、Lock、Write;其中 Default 中的 key 包含数据 key+TSO;Lock 存储锁信息,注意一个事务中操作如果存在多行操作,只会给第一行加一个主锁,其他行均依附于该主锁。下图示例中 3 代表数据 keyID,W 代表为写锁,100 为事务的开始时间戳

  3. commit:commit timestamp=110。从 PD 中获取事务结束的 TSO,在 write 列簇中写入,如下图所示包含 keyid+ 提交的时间戳,以及对应事务开始的时间戳。清理锁信息,在 Lock 中删除对应的锁。注意删除并非直接删除数据,而是新增一个 D 的锁数据,代表其为删除。

  4. 其他人想要读取 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 日志复制

步骤


  1. propose:客户端将写入信息发送给 TiKV 节点(对应 region 的 leader 节点)



  1. append:leader 接收到写入请求,将内容写入到 raft 日志中 (格式:reaginId_ 序号,log{PUT key=xx,name=xx},存储在 leader 当前节点的 raftDb 中,用来专门存放 raft log 的 Db)



  1. replicate:将日志内容传递给 follower,



  1. committed:当多数的节点返回 append 成功消息后,视为 committed 成功。(此 committed 不是指 sql 应用中的 committed,仅仅指 raft log 的 committed)



  1. 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 所示



  1. 过滤:将每个节点的 order、product 数据按查询条件的范围进行过滤,查询出结果放到内存中。



  1. 数据交换:通过 hash 函数将 order、product 值相等的数据交换到同一个节点中



  1. Join:各个节点并行 join 查询



  1. 数据交换:再基于 state 取 hash 函数运算,进行数据交换将相等的数据放置到同一个节点



  1. 聚合:各个节点聚合,得出结果


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 一致性读取
  1. T0 时刻从客户端写入 2 行数据,key1=100 和 key999=7,正好在不同的 region 中,对应的 raft log 的 idx 分别为 101、22。

  2. 此时 TiFlash 第一个 region 的 idx 写入到 95,第二个的 idx 写入到 18。因为异步复制,当前没数据也正常。

  3. T1 时刻客户端向 TiFlash 读取 key1 和 key999 的值。

  4. 此时 TiFlash 的 idx 分别到了 108 和 20;tikv 的 idx 当前分别为 120 和 29。

  5. 这时 key1 的值已经在 tiflash 中了,key2 的值还没有,而且也没发保障当前 2 个 region 在 tiflash 中都存储了之前写入的数据,这时 tiFlash 需要去询问 TiKV 当前的 idx

  6. 在 Tiflash 询问 idx 前的,T2 时刻这时客户端又将 key1 的值写入为 200,此时当前的 TiKV 的 idx 为 122

  7. T3 时刻 tiflash 询问了 tikv 节点,从 tikv 中获取了当前 tikv 的 idx,分别为 125 和 31,记录为 Wait idx。

  8. 该请求操作非常轻量。

  9. 此时 TiKV 就以这 2 个 Wait idx 来等,等到后就能保障之前的写入数据一定能进入到 TiFlash 中。

  10. T4 时刻 tiflash 黄色 region 等到了 31idx 写入,此时 key999 能读取到 7 了

  11. T5 时刻 tilflash 绿色 region 等到了 125,去读取 key1 发现有 2 个版本,分别对应 idx101 和 122

  12. 由于该读取请求时在 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


发布于: 3 小时前阅读数: 7
用户头像

TiDB 社区官网:https://tidb.net/ 2021-12-15 加入

TiDB 社区干货传送门是由 TiDB 社区中布道师组委会自发组织的 TiDB 社区优质内容对外宣布的栏目,旨在加深 TiDBer 之间的交流和学习。一起构建有爱、互助、共创共建的 TiDB 社区 https://tidb.net/

评论

发布
暂无评论
PCTA认证-101课程学习笔记_学习&认证&课程_TiDB 社区干货传送门_InfoQ写作社区