1 简介

TiDB支持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和 MySQL 协议,具有数据强一致的高可用特性,是一个不仅适合 OLTP 场景还适OLAP 场景的混合数据库。

开发语言 SQL层:GO TiKV分布式存储引擎: Rust

文档:
https://docs.pingcap.com/zh/tidb/stable/overview
https://zhuanlan.zhihu.com/p/71073707

应用场景:

  • 海量数据、高并发 OLTP 系统(高并发写入、水平扩展、分布式事务、强一致性、在线DDL、高可用)。
  • 海量数据、高性能实时分析 HTAP(实时风控/数仓/报表)。

TiDB 实践
今日头条:http://t.cn/RnLfEMf
游族平台:https://mp.weixin.qq.com/s/_VAWuTO2KUlGB8B0ouLRTw
马蜂窝:https://www.slidestalk.com/TUG/MongoDBTiDB65928
同程旅游:https://segmentfault.com/a/1190000014361145
易果集团(实时数仓):http://t.cn/RTYVhzH
二维火餐饮(实时报表):https://mp.weixin.qq.com/s/Ui3i2xhvPB_gig3WU_2Jaw

对比MySQL
不支持的特性

  • 存储过程
  • 视图
  • 触发器
  • 自定义函数
  • 外键约束
  • 全文索引
  • 空间索引
  • 非 UTF8 字符集

有差异的特性

  • 自增 ID
  • 内建函数
  • 在线 DDL
  • 事务
  • Load data


2 架构

TiDB 最佳实践.pdf
image.png

TiDB Server
至少2台, 集群万兆网卡。
接收并处理SQL请求,通过PD找到数据的 TiKV 地址并返回结果。
其本身并不存储数据,只负责计算,可以无限水平扩展,可以通过负载均衡组件(如LVS、HAProxy 或 F5)对外提供统一的接入地址。

TiKV Server
至少3台,与 TiDB 分开部署,以免竞争 CPU, 使用 本地SSD 磁盘。

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

PD Server
必须3台。
Placement Driver,整个集群的管理模块,其主要工作有三个:

  • 一是存储集群的元信息(某个 Key 存储在哪个 TiKV 节点);
  • 二是对 TiKV 集群进行调度和负载均衡(如数据的迁移、Raft group leader 的迁移等);
  • 三是分配全局唯一且递增的事务 ID。
  • PD 是一个集群,需要部署奇数个节点,一般线上推荐至少部署 3 个节点。

image.png
image.png

3 负载均衡

  • 存储的负载均衡
  • 计算的负载均衡
  • 下线节点
  • 上线节点

PD 会根据整个 TiKV 集群的状态, 对集群的负载进行调度。 以 Region 为单位,以 PD 配置的策略为调度逻辑,自动完成。

4 SQL 在 KV 原理

  • Database/Table 的元信息(定义、属性、Schema信息等)会分配一个唯一的 ID 标识,存储在 TiKV 中,编码成 KV 对,key: ID+m_前缀,value: 序列化后的元数据
  • 表:TiDB 对每个表分配一个 TableID (整个集群内唯一);
  • 行:每一行分配一个 RowID(表内唯一, 如果表有整形的 Primary Key,那么会用 Primary Key 的值当做 RowID);
  • 这些ID都是int64类型。每行数据按照如下规则进行编码成Key-Value pair:

    1. Key tablePrefix_rowPrefix_tableID_rowID
    2. Value: [col1, col2, col3, col4]
  • 索引:每一个索引都会分配一个 IndexID (表内唯一),映射为KV,key 以 TableID+indexID 构造前缀,以索引值构造后缀;

    1. -- 唯一索引
    2. Key: tablePrefix_idxPrefix_tableID_indexID_indexColumnsValue
    3. Value: rowID
    4. -- 非唯一
    5. Key: tablePrefix_idxPrefix_tableID_indexID_ColumnsValue_rowID
    6. Valuenull

    参考:https://www.cnblogs.com/xuliuzai/p/10022875.html

xxPrefix都是字符串常量。 定义如下: var( tablePrefix = []byte{‘t’} recordPrefixSep = []byte(“_r”) indexPrefixSep = []byte(“_i”) )

5 TiDB 表设计

表特性:

  • 行存储格式,全局排序。
  • 主键:业务列,自增主键,隐式主键。
  • 超级超宽表:经验值单行大小 < 64K。
  • 顺序扫描,尽量减少逆序 scan。
  • 主键、索引连续还是离散?
  • N + 1 KV Pairs 的写入,事务模型保证一致性。
  • 一行的数据都是存在一个 KV Pair 中,不会被切分。
  • 一次体检的全部数据 小于 100 MB.

考虑 TiDB 做编码以及事务额外 key 的开销,建议每个事务的行数不多于一万。
建议 Insert、Update、Delete 语句,都通过分 Batch 提交或增加 Limit 限制。

6 数据导入与写入

7 查询及优化

查看执行计划

  1. EXPLAIN select * from A

查询并终止连接

  1. SHOW PROCESSLIST;
  2. KILL TIDB id;

8 注意事项

  • 删除大数据量的时候,用小数据量多批量方式操作,如每次 1000 条。
  • 大批量数据导入后,建议操作: analyze table table_name