本文是《极客时间》-《TiDb极简入门》的学习笔记。传送门:https://time.geekbang.org/opencourse/videointro/100089601
这部分讲解了Tidb的整体概述。
一 我们需要一个什么样的数据库?
数据库设计要考虑什么
1.扩展性 scale-out
颗粒度越小越好,常见的颗粒度:集群/db/表/分表/分区表
写入能力的线性扩展
2.强一致,高可用
强一致: CAP里的一致性(副本一致性)
由于副本节点数和网络延迟成正比,节点数量越多,网络延迟越大。 普遍采用多数派强一致,常见的3副本强制写2节点
数据容灾:RPO(数据恢复点目标)所能容忍的数据容量量
rto(恢复时间目标)所能容忍业务停止服务的最长时间
强一致,高可用目标是实现RPO=0,RTO足够小(目前普遍是若干秒级)
3.实现标准SQL与事务的支持
因为SQL是高度易用性,已经是数据交互类语言的实施标准,所以兼容sql非常重要
同时在很多场景下,尤其是oltp,完整事务是必选项
4.云原生
5混合数据服务HTAP
在海量数据下OLTP OLAP的数据服务融合
行列混合
更彻底的资源隔离
6.兼容主流生态协议
数据技术栈领域里常见的基础因素
1. 数据模型: 关系模型/ 文档模型/KV模型
2. 数据存储与检索结构:B-Tree/LSM-Tree/分形树
3. 数据格式:结构化数据/非结构化数据/半结构化数据
4. 存储引擎:负责数据的存储和持久化:Inno DB Rocks DB
5. 复制协议:保证数据的可用性,Raft/Paxos
6. 分布式事务模型:事务处理时的并发处理方法,以保证事务的可串行化 XA/Percolato
7. 数据架构:多个计算引擎共享同一份数据/多份数据,常见的有 Share-Disk/Share-Nothing/Share-Everything等
8. 优化器算法:根据数据分布/统计信息生成成本最低的执行计划
9. 执行引擎:火山引擎/向量化/大规模并行计算等
10.计算引擎:是否是一个标准SQL的引擎
计算与存储分离的必然性
1. 计算与存储绑定,意味着总有一个资源是浪费的
2. 服务器选型困难
3. 在云计算场景下,弹性的颗粒度是机器,不能做到真正资源的弹性
TiDB高度分层架构
弹性是整个架构设计的核心考量点,计算与存储分离
从逻辑上TiDb主要分为3层
1.TiDB-Server: 支持标准SQL的计算引擎(以Mysql5.7为主,在逐步兼容Mysql8.0), 本身并不存储数据,只进行计算
2.TiKv: 分布式存储引擎
3.Placement Driver(PD): 负责元信息与调度引擎,整个集群的大脑,为了保证高可用性,至少有3个节点,通过raft复制。
PD有以下几个功能:
集群的元信息管理:分片的分布,拓扑结构
分布式事务ID的分配
调度中心
二 如何构建一个分布式存储系统
我们需要一个什么样的存储引擎
1.更细粒度的弹性扩缩容
2.高并发读写
3.数据不丢不错
4.多副本保障一致性及高可用性
5.支持完整的分布式事务
TiDb 的选择
数据结构
选择了KV的数据索引, 简单随处可见,而且是其他更复杂索引基础构建的模块
存储引擎
选择了基于LSM-Tree的RocksDB引擎
支持批量写入
无锁快照读
为什么不用B-Tree:
在传统的OLTP系统中,写入是最昂贵的成本
B-Tree至少要写两次,一次预写(WAL),一次写入树本身,
B-Tree是严格平衡的数据结构,他的设计是对读友好,数据写入触发的B-Tree分裂与平衡成本是非常高的,因此B-Tree相对于写入并不友好
在传统的主从架构里,不管加多少个节点,集群的写入容量完全由主哭的机器配置决定,扩容只能通过分库(集群拆分)来进行
因此选择了LSM-Tree,本质是用空间置换写入延迟,用顺序写入替代随机写入到数据结构
采用顺序写,写到了一定阈值以后,持久化成一个静态文件,随着静态文件越来越大,会被推到下一层进行合并
数据副本
数据冗余决定了系统可用性
强一致数据算法:raft
对比Paxos, Raft的目标是提供更清晰的逻辑分工,使得算法本身能被更好地理解,同时他的安全性更高,能提供一些额外的特性。(from wiki)
如何实现扩展
做分片,预先分片还是自动分片?
传统的分库分表属于预先分片,只解决了表容量问题,没有解决弹性问题
分片算法:哈希,范围,列举
Tikv采取了范围,原因
1. 在“where 字段> value”的场景下,在这个场景下,range分片可以更高效的扫描数据
2. 可以简单实现自动完成分裂和合并
3. 弹性有限,分片需要可以自由调度,range对于自由调度更友好
range分片的问题
1.需要考虑热点问题?
region概念
把Tikv看成是一个巨大的有序的kv map,通过范围的方式,将整个kv空间分成若干段,每一段也是一些列连续的kv,把每一段成为region, 并且尽量保证每个region中保存的数据不超过一定的大小
如何进行分离与扩展
当region超过一定大小,会自动分成两个region, 当由于大量删除请求导致region变小,会自动和相邻的region合并
灵活调度机制
PD来负责将region尽可能的,均匀的,离散的,分布在集群的所有节点上。
1.实现了存储容量的水平扩展,通过增加新的节点会自动将其他节点上的region分片调度过来
2.实现了负载均衡
TiKv整体架构
参考率goole spanner设计的multi raft-group副本机制
多版本控制MVCC
通过在key后面增加版本号实现
分布式事务模型
参考了google的percolator事务模型
去中心化两阶段提交
每个节点单独分配区域存放锁信息(Tikv的锁是基于列簇,CF lock)
通过PD全局授时(TSO)
TIDB默认隔离级别是SI(快照隔离),也支持RC(read commit)
默认乐观锁,在3.0以后也支持悲观锁,可以自由选择,在5.0以后,实现了两阶段异步提交
协作处理器Coprocessor
tikv中读取数据的计算模块
在数据层尽快的进行计算和预处理,例如在本地节点尽快完成filter,group by等
三 如何构建一个分布式sql引擎
如何在kv上实现逻辑表
每个表有一个tableid, 每个索引indexid, 每行有rowid
简单来看,key = rowid indexid
value=所有列按等位偏移的方式进行connect进行连接
在数据查询的时候,我们通过等位偏移对value进行反解析,然后对应schema的元信息进行列信息映射
二级索引:也是一个全局有序的kvmap
简单来说:key= 索引列信息
value= primary-key
然后通过pk在原表查数据,类似于b-tree的回表
sql引擎过程
SQL: sql语法解析/语义解析
抽象语法树:从文本解析成结构化数据
逻辑优化:将各种sql等价改写以及优化
物理优化:基于统计信息与成本进行生产执行计划(重要)
执行引擎:根据优化器定下的执行路径进行数据寻址,数据计算
基于成本优化器
cost model里需要进行合理的匹配计算
分布式sql引擎主要优化策略
最大程度让数据在分布式存储层尽快的完成过滤以及预计算(最大下推策略 push down)
关键算子分布式化
如何构建一个Online DDL
1.tidb没有分表概念,所以整个ddl完成过程是很快的,秒回
2.ddl过程分成public/delete-only/write-only等几个状态,每个状态在多节点之间同步和一致,完成最终的ddl(根据goggle的f1论文)
如何连接到tidb-server
可以使用mysql客户端或者sdk直接连接
从进程的角度看tidb-server
就是一个后台进程,不断监听port,和client通信,按照mysql协议解析收到的网络请求,获取时间戳,通过分片的路由信息找到对应的存储节点去查询数据
从内部角度看tidb-server
mysql协议层
sql核心层:sql的parse分析,逻辑优化,物理优化,统计信息收集,执行层等
其他功能
前台功能
1.管理连接和账号权限管理
2.mysql协议编码解码
3.独立sql执行
4.库表元信息,系统变量管理
后台功能
1.GCC
2.执行DDL
3.统计信息收集
4.sql优化器与执行器