TiDB学习笔记

0 阅读12分钟

TiDB介绍

什么是TiDB

TiDB 是一个分布式的 NewSQL 数据库。它支持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和 MySQL 协议,具有数据强一致的高可用特性,是一个不仅适合 OLTP 场景(on-line transaction processing,联机事务处理)还适合 OLAP 场景(On-Line Analytical Processing,联机分析处理)的混合数据库。

NewSQL

NewSQL 是一类诞生于互联网大规模数据和高并发场景的数据库技术,其核心目标是同时兼顾传统关系型数据库的强事务性(ACID)、SQL 兼容性,以及 NoSQL 的分布式扩展性

OLTP

  • 支持短时间内大量并发的事务操作(增删改查)能力,每个操作涉及的数据量都很小(比如几十到几百字节)
  • 支持事务的强一致性

OLAP

  • 偏向于复杂的只读查询,读取海量数据进行分析计算

开发语言

TiDB整个项目分为两层,TiDB 作为 SQL 层,采用 Go 语言开发, TiKV 作为下边的分布式存储引擎,采用 Rust 语言开发。

对比传统单机数据库的优势

  • 纯分布式架构,拥有良好的扩展性,支持弹性的扩缩容
  • 支持 SQL,对外暴露 MySQL 的网络协议,并兼容大多数 MySQL 的语法,在大多数场景下可以直接替换 MySQL
  • 默认支持高可用,在少数副本失效的情况下,数据库本身能够自动进行数据修复和故障转移,对业务透明
  • 支持 ACID 事务,对于一些有强一致需求的场景友好,例如:银行转账
  • 具有丰富的工具链生态,覆盖数据迁移、同步、备份等多种场景

架构设计

架构图

image.png

image.png TiDB Server
​TiDB Server 负责接收 SQL 请求,处理 SQL 相关的逻辑并通过 PD Server找到存储计算所需数据的TiKV 地址,与 TiKV 交互获取数据,最终返回结果。TiDB Server 是无状态的,其本身并不存储数据,只负责计算,可以无限水平扩展,可以通过负载均衡组件(如LVS、HAProxy 或 F5)对外提供统一的接入地址

PD Server
Placement Driver (简称 PD) 是整个集群的管理模块,其主要工作有三个:

  • 存储集群的元信息(某个 Key 存储在哪个 TiKV 节点);
  • 对 TiKV 集群进行调度和负载均衡(如数据的迁移、Raft group leader 的迁移等);
  • 分配全局唯一且递增的事务 ID。

PD 通过 Raft 协议保证数据的安全性。Raft 的leader server 负责处理所有操作,其余的 PD server 仅用于保证高可用。建议部署奇数个 PD 节点,一般线上推荐至少部署 3 个节点。

TiKV Server
​TiKV Server 负责存储数据,从外部看 TiKV 是一个分布式的提供事务的 Key-Value 存储引擎。存储数据的基本单位是Region,每个 Region 负责存储一个 Key Range(从 StartKey 到 EndKey 的左闭右开区间)的数据,每个TiKV 节点会负责多个 Region。TiKV 使用 Raft 协议做复制,保持数据的一致性和容灾。副本以 Region 为单位进行管理,不同节点上的多个 Region 构成一个 Raft Group,互为副本。数据在多个 TiKV 之间的负载均衡由 PD 调度,这里也是以 Region 为单位进行调度

TiSpark
​TiSpark 作为TiDB中解决用户复杂 OLAP 需求的主要组件,将 Spark SQL 直接运行在 TiDB 存储层上,同时融合 TiKV 分布式集群的优势,并融入大数据社区生态。至此,TiDB可以通过一套系统,同时支持OLTP与OLAP,免除用户数据同步的烦恼

TiDB Operator
​TiDB Operator 提供在主流云基础设施(Kubernetes)上部署管理 TiDB 集群的能力。它结合云原生社区的容器编排最佳实践与 TiDB 的专业运维知识,集成一键部署、多集群混部、自动运维、故障自愈等能力,极大地降低了用户使用和管理 TiDB 的门槛与成本

核心特性:水平扩展与高可用

高度兼容 MySQL
​大多数情况下,无需修改代码即可从 MySQL 轻松迁移至 TiDB,分库分表后的 MySQL 集群亦可通过 TiDB 工具进行实时迁移。对于用户使用的时候,可以透明地从MySQL切换到TiDB 中,只是“新MySQL”的后端是存储“无限的”,不再受制于Local的磁盘容量。在运维使用时也可以将TiDB当做一个从库挂到MySQL主从架构中。

分布式事务
TiDB 100% 支持标准的 ACID 事务。

一站式 HTAP 解决方案
HTAP: Hybrid Transactional/Analytical Processing
TiDB 作为典型的 OLTP 行存数据库,同时兼具强大的 OLAP 性能,配合 TiSpark,可提供一站式 HTAP 解决方案,一份存储同时处理 OLTP & OLAP,无需传统繁琐的 ETL 过程。

云原生 SQL 数据库
TiDB 是为云而设计的数据库,支持公有云、私有云和混合云,配合 TiDB Operator 项目 可实现自动化运维,使部署、配置和维护变得十分简单。

水平弹性扩展
通过简单地增加新节点即可实现 TiDB 的水平扩展,按需扩展吞吐或存储,轻松应对高并发、海量数据场景。

水平扩展

无限水平扩展是 TiDB 的一大特点,这里说的水平扩展包括两方面:计算能力(TiDB)和存储能力(TiKV)。

  • TiDB Server 负责处理 SQL 请求,随着业务的增长,可以简单的添加 TiDB Server 节点,提高整体的处理能力,提供更高的吞吐
  • TiKV 负责存储数据,随着数据量的增长,可以部署更多的 TiKV Server 节点解决数据 Scale 的问题。
  • PD 会在 TiKV 节点之间以 Region 为单位做调度,将部分数据迁移到新加的节点上。

所以在业务的早期,可以只部署少量的服务实例(推荐至少部署 3 个 TiKV, 3 个 PD,2 个 TiDB),随着业务量的增长,按照需求添加 TiKV 或者 TiDB 实例。

高可用

高可用是 TiDB 的另一大特点,TiDB/TiKV/PD 这三个组件都能容忍部分实例失效,不影响整个集群的可用性。

下面分别说明这三个组件的可用性、单个实例失效后的后果以及如何恢复。
TiDB
TiDB 是无状态的,推荐至少部署两个实例,前端通过负载均衡组件对外提供服务。当单个实例失效时,会影响正在这个实例上进行的 Session,从应用的角度看,会出现单次请求失败的情况,重新连接后即可继续获得服务。单个实例失效后,可以重启这个实例或者部署一个新的实例。

PD
PD 是一个集群,通过 Raft 协议保持数据的一致性,单个实例失效时,如果这个实例不是 Raft 的 leader,那么服务完全不受影响;如果这个实例是 Raft 的 leader,会重新选出新的 Raft leader,自动恢复服务。PD 在选举的过程中无法对外提供服务,这个时间大约是3秒钟。推荐至少部署三个 PD 实例,单个实例失效后,重启这个实例或者添加新的实例。

TiKV
TiKV 是一个集群,通过 Raft 协议保持数据的一致性(副本数量可配置,默认保存三副本),并通过 PD 做负载均衡调度。单个节点失效时,会影响这个节点上存储的所有 Region。对于 Region 中的 Leader 节点,会中断服务,等待重新选举;对于 Region 中的 Follower 节点,不会影响服务。当某个 TiKV 节点失效,并且在一段时间内(默认 30 分钟)无法恢复,PD 会将其上的数据迁移到其他的 TiKV 节点上。

存储和计算

存储能力-TiKV-LSM
​TiKV Server通常是3+的,TiDB每份数据缺省为3副本,这一点与HDFS有些相似,但是通过Raft协议进行数据复制,TiKV Server上的数据的是以Region为单位进行,由PD Server集群进行统一调度,类似HBASE的Region调度。
​TiKV集群存储的数据格式是KV的,在TiDB中,并不是将数据直接存储在 HDD/SSD中,而是通过RocksDB实现了TB级别的本地化存储方案,着重提的一点是:RocksDB和HBASE一样,都是通过 LSM树作为存储方案,避免了B+树叶子节点膨胀带来的大量随机读写。从而提升了整体的吞吐量。

计算能力-TiDB Server
​TiDB Server本身是无状态的,意味着当计算能力成为瓶颈的时候,可以直接扩容机器,对用户是透明的。理论上TiDB Server的数量并没有上限限制。

性能

1)基于CBO(Cost-Based Optimization)优化器:使用最小代价的物理计划优化算法,率先在Oracle7上使用,现在主流数据库都已经采用了CBO优化器

2)向量化:利用SIMD指令集,充分发挥CPU的处理能力,一些新型的分布式数据库也均已采用全面向量化,如doris,clickhouse等

3)协处理:将计算尽量靠近存储节点,TiFlash 和TIKV同时都拥有协处理的能力,类似于谓词下推,可以将计算下推到TiFlash和TIKV,从而利用分布式计算能力,且减少RPC的调用次数以及传输的数据量,最终提高计算性能

4)行存(TIKV)和列存(TiFlash)同时存在,并且能智能选择最优的执行计划(需要保证表的健康度)

注意事项

1)如果不Order by ,每次返回的数据顺序都不一致
在单机数据库中由于数据都存储在一台服务器上,有些数据库(尤其是 MySQL InnoDB 存储引擎)还会按照主键或索引的顺序进行结果集的输出,所以每次查询返回的数据顺序相对稳定。
而TiDB 是分布式数据库,数据被存储在多台服务器上,多份数据返回的时间先后并不固定。另外 TiDB 层不缓存数据页,因此不含 order by 的 SQL 语句查询出来的结果集的数据顺序无法保证一致。

2)自增列不能保证连续

TiDB中自增列只保证自增且唯一,并不保证连续
TiDB目前采用批量分配的方式,所以如果在多台 TiDB 上同时插入数据,分配的自增 ID 会不连续。当多个线程并发往不同的 tidb-server 插入数据的时候,有可能会出现后插入的数据自增 ID 小的情况。

TiDB 实现自增 ID 的原理是每个 tidb-server 实例缓存一段 ID 值用于分配(目前会缓存 30000 个 ID),用完这段值再去取下一段。在集群中有多个 tidb-server 时,人为向自增列写入值之后,可能会导致 TiDB 分配自增值冲突而报 “Duplicate entry” 错误。

3)表的健康度要关注

TIDB采用CBO优化器来生成物理执行计划,当某个表的健康度降低的时候,会导致CBO执行器无法准确判断走哪个索引的代价更小,从而导致选择错误的索引,而导致查询性能较低。

通过 SHOW STATS_HEALTHY 可以查看表的统计信息健康度,并粗略估计表上统计信息的准确度。当 modify_count >= row_count 时,健康度为 0;当 modify_count < row_count 时,健康度为 (1 - modify_count/row_count) * 100。
健康度越高,执行器选择正确的索引的成功率越高。
TiDB会自动收集表信息,可以通过下面语句查询TIDB执行收集信息的时间和阀值。

show variables like '%analyze%'

tidb_auto_analyze_ratio 默认为0.5,表示健康度低于50的时候在tidb_auto_analyze_start_time 和 tidb_aotu_analyze_end_time的时间范围内会自动执行analyze table table_name 来收集信息。(ps: +0000表示时区,+0800是东八区)

4)注意谓词下推,很多函数不支持

5)事务超时

含 DML 语句的事务,除了受 tikv_gc_life_time 限制之外,还受到另外一个参数 max-txn-time-use 的影响,这个参数位于 tidb-server 的配置文件 tidb.toml 中,用于控制单个事务允许的最大执行时间。该参数的默认值为 590(秒),需要注意必须控制该参数的值小于 tikv_gc_life_time 的值。
如 insert into t2 select * from t1的 SQL 语句,即使执行时间没有达到 tikv_gc_life_time 限制,但超过了 max-txn-time-use 的限制,会由于超时而回滚。

6)OOM问题

TIKV由于是KV结构存储的,不具备Join能力,如果查询语句中有关联表没有Tiflash,则必须要将TIKV中的所有数据都拉取到TiDB节点再进行处理,此时极易产生OOM。应当尽量避免此类情况产生,也可以通过设置SQL内存的方式来增大内存使用量。

例如:
配置整条 SQL 的内存使用阈值为 8GB:

SET tidb_mem_quota_query = 8 << 30;

配置整条 SQL 的内存使用阈值为 8MB:

SET tidb_mem_quota_query = 8 << 20;

7)Index Merge 只支持 or ,不支持 and

TiDB 4.0之后开始支持Index Merge,但是目前6.2版本也支持or的操作,对于and的查询操作仍然是不支持的。那就意味着在创建索引的时候不能向MySQL那样创建多个单独索引,而是需要根据实际使用的场景建立联合索引(这点尤为重要)。

TIDB的部署

1)因 TiDB 和 PD 对磁盘 IO 要求不高,所以只需要普通磁盘即可。

2)TiKV 对磁盘 IO 要求较高。TiKV 硬盘大小建议不超过 500G,以防止硬盘损害时,数据恢复耗时过长。整个 TiDB 架构是面向未来、面向海量数据高并发场景,底层存储技术(如数据定位 seek)都是针对当前主流的 SSD 进行设计和优化的,不会对传统的 SATA/SAS 机械硬盘再进行优化。

3)部署工具使用了 TiDB-Ansible。TiDB-Ansible 是 PingCap 基于 Ansible playbook 功能编写了一个集群部署工具叫 TiDB-Ansible。使用该工具可以快速部署一个完整的 TiDB 集群(包括 PD、TiDB、TiKV 和集群监控模块)。