简介
-
TiDB是一个兼容MySql协议的分布式数据库,对比普通单机数据库有以下优势
- 纯分布式架构,拥有良好的扩展性,支持弹性的扩缩容
- 支持 SQL,对外暴露 MySQL 的网络协议,并兼容大多数 MySQL 的语法,在大多数场景下可以直接替换 MySQL
- 默认支持高可用,在少数副本失效的情况下,数据库本身能够自动进行数据修复和故障转移,对业务透明
- 支持 ACID 事务,对于一些有强一致需求的场景友好,例如:银行转账
- 具有丰富的工具链生态,覆盖数据迁移、同步、备份等多种场景
-
主要由三个部分组成:集群的元信息管理模块PD、SQL解析层TiDB Server、数据存储层TiKV和TiFlash
数据存储层
- TiDB可选择行存储的TiKV和列存储的TiFlash两种存储引擎,他们底层都使用RocksDB的KV进行存储,以Region(有序的key,大小默认96M)为单位存储副本
- TiKV作为行存储可以满足OLTP(在线事务处理)的特性
- TiFlash作为列存储可以满足OLAP(在线分析处理)的特性,并且他不能单独插入数据,只能基于TiKV的某个Region作为raft group的learner角色进行异步复制数据
- Region是作为集群操作的最小单元,当空间使用超过/降低到一定的阈值(144M/20M),会进行Region的拆分/相邻合并
- 避免单机问题以Region为单位进行多副本存储,一个Region为Raft group进行多副本同步。raft的日志同步是在rocksDB存储之上进行的,是先同步再分批leader/follower/learner各自写入自己的rocksDB实例
- 也提供了MVCC多版本控制,是基于RocksDB本身的多版本控制来实现的,会多存储一些版本号,老旧的版本数据会在一定时间后删除
TiDB Server
-
TiDB Server本身不存储任何中间数据,作为集群可以使用负载均衡分担客户端的请求;客户端用户使用的是SQL的协议和语法,在存储底层使用的是RocksDB的KV存储,因此需要TiDB Server做一个转换
-
表和记录与有序KV存储之间映射关系
- 每个表都有唯一的tableId;每一行数据都有唯一的rowId,每个索引行都有唯一的indexId
- 一行数据:key = t{TableID}_r{RowID},value = 一行数据字段使用逗号分割
- 唯一索引:key = t{tableID}_i{indexID}_indexedColumnsValue, value = rowId
- 普通索引:key = t{TableID}_i{IndexID}indexedColumnsValue{RowID},value = null
-
其他功能:处理客户端的连接、在线DDL的执行、回收TiKV历史版本的数据
PD
- 是整个集群的大脑,主要提供以下功能:
- 存储每个TiKV节点数据分布情况和整体拓扑结构、下发数据平衡命令给具体的TiKV节点、leader数量在节点之间均匀分配、多个Region副本不在同一个节点
- 提供TiDB Dashboard管控界面
- 为分布式事务分配事务ID
- 每个TiKV节点会定期向PD汇报节点的状态信息,大概包含下列信息
- 总磁盘容量
- 可用磁盘容量
- 承载的Region 数量
- 数据写入/读取速度
- 发送/接受的 Snapshot 数量(副本之间可能会通过 Snapshot 同步数据)
- 是否过载
- labels 标签信息(标签是具备层级关系的一系列 Tag,能够感知拓扑信息
- 每个Raft Group的Leader会定期向PD汇报Region的状态信息,主要包括下列信息
- Leader 的位置
- Followers 的位置
- 掉线副本的个数
- 数据写入/读取的速度
分布式事务
分为乐观锁和悲观锁,因为RocksDB的一个key就相当于一行数据数据,因此也是采用类似mysql锁的形式,对所有leader Region中对应的key加锁,进行2PC协议进行分布式事务提交,性能依旧会有降低,乐观锁的流程大致如下