当前位置 : 首页 » 文章分类 :  开发  »  TiDB

TiDB

TiDB学习笔记

PingCAP官方文档
https://pingcap.com/docs-cn/stable/

《TiDB in Action》 中文版 gitbook
https://book.tidb.io/
https://github.com/pingcap-incubator/tidb-in-action

TiDB 的正确使用姿势
https://segmentfault.com/a/1190000008643974


概述

TiDB 是 PingCAP 公司设计的开源分布式 HTAP(Hybrid Transactional and Analytical Processing) 数据库,结合了传统的 RDBMS 和 NoSQL 的最佳特性。

它的设计目标是100%的 OLTP(Online Transactional Processing) 场景和 80% 的 OLAP(Online Analytical Processing) 场景,更复杂的 OLAP 分析可以通过 TiSpark 来完成。力图为 OLTP 和 OLAP 场景提供一站式的解决方案。

TiDB 对业务没有任何侵入性,且能兼容 MySQL,能优雅的替换传统的数据库中间件、数据库分库分表等 Sharding 方案,大多数情况下无需修改代码即可从 MySQL 轻松迁移至 TiDB,分库分表后的 MySQL 集群亦可通过 TiDB 工具进行实时迁移。

TiDB 能够 100% 支持标准的 ACID 事务,同时支持无限的水平扩展,通过简单地增加新节点即可实现 TiDB 的水平扩展,按需扩展吞吐或存储,轻松应对高并发、海量数据场景,让开发运维人员不用关注数据库 Scale 的细节问题,专注于业务开发。

并且相比于传统主从 (M-S) 复制方案,基于 Raft 的多数派选举协议可以提供金融级的 100% 数据强一致性保证,且在不丢失大多数副本的前提下,可以实现故障的自动恢复 (auto-failover),无需人工介入。

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

整体架构

TiDB 集群主要包括三个核心组件:TiDB Server,PD Server 和 TiKV Server。此外,还有用于解决用户复杂 OLAP 需求的 TiSpark 组件和简化云上部署管理的 TiDB Operator 组件。

TiDB Server

TiDB Server 负责接收 SQL 请求,处理 SQL 相关的逻辑,并通过 PD 找到存储计算所需数据的 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 节点。

TiKV Server

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

TiKV 使用 Key-Value 模型存储数据,并且提供有序遍历方法。
简单来讲,可以将 TiKV 看做一个巨大的 Map,其中 Key 和 Value 都是原始的 Byte 数组,在这个 Map 中,Key 按照 Byte 数组总的原始二进制比特位比较顺序排列。
TiKV 的两个特性:
这是一个巨大的 Map,也就是存储的是 Key-Value pair
这个 Map 中的 Key-Value pair 按照 Key 的二进制顺序有序,也就是我们可以 Seek 到某一个 Key 的位置,然后不断的调用 Next 方法以递增的顺序获取比这个 Key 大的 Key-Value


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

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


为什么用tidb?

1、mysql 单机无法适应爆发式的数据存储需求,无法灵活 scale

2、兼容mysql协议,可直接使用 mysql connector 连接,mybatis Generator 生成mapper。
兼容mysql 语法,无需额外的学习成本。

相比mysql的优势

可在线扩展:数据通常要有分片,分片要支持分裂和自动迁移,并且迁移过程要尽量对业务无感知。
支持 ACID 的强一致的分布式事务:事务可以跨分片、跨节点执行,并且强一致。


原理

RocksDB

TiKV 底层使用 Facebook 开源的 RocksDB 存储引擎,RocksDB 是一个单机的 Key-Value Map,基于 Google 开源的 LevelDB 引擎构建。

RocksDB是使用C++编写的嵌入式kv存储引擎,其键值均允许使用二进制流。由Facebook基于levelDB开发。
RocksDB使用LSM存储引擎

LSM-Tree(Log-Structured-Merge-Tree)


LevelDB


Raft

TiKV 利用 Raft 来做数据复制,每个数据变更都会落地为一条 Raft 日志,通过 Raft 的日志复制功能,将数据安全可靠地同步到 Group 的多数节点中。

TiKV 是以 Region 为单位做数据的复制,也就是一个 Region 的数据会保存多个副本,我们将每一个副本叫做一个 Replica。Replica 之间是通过 Raft 来保持数据的一致(终于提到了 Raft),一个 Region 的多个 Replica 会保存在不同的节点上,构成一个 Raft Group。其中一个 Replica 会作为这个 Group 的 Leader,其他的 Replica 作为 Follower。所有的读和写都是通过 Leader 进行,再由 Leader 复制给 Follower。


Region

对于一个 KV 系统,将数据分散在多台机器上有两种比较典型的方案:一种是按照 Key 做 Hash,根据 Hash 值选择对应的存储节点;另一种是分 Range,某一段连续的 Key 都保存在一个存储节点上。

key range sharding: 一个 shard 过大后需要再次拆分时,只需要拆为更小的 range, 不需要数据迁移。
hash sharding: resharding 时需要 rehash,代价较高。

TiKV 选择了第二种方式,将整个 Key-Value 空间分成很多段,每一段是一系列连续的 Key,我们将每一段叫做一个 Region,并且我们会尽量保持每个 Region 中保存的数据不超过一定的大小(这个大小可以配置,目前默认是 64mb)。每一个 Region 都可以用 StartKey 到 EndKey 这样一个左闭右开区间来描述。

将数据划分成 Region 后,我们将会做 两件重要的事情:

  • 以 Region 为单位,将数据分散在集群中所有的节点上,并且尽量保证每个节点上服务的 Region 数量差不多
  • 以 Region 为单位做 Raft 的复制和成员管理

特性

自增主键

过度依赖单调递增的主键,AUTO INCREMENT ID
在传统的关系型数据库中,开发者经常会依赖自增 ID 来作为 PRIMARY KEY,但是其实大多数场景大家想要的只是一个不重复的 ID 而已,至于是不是自增其实无所谓,但是这个对于分布式数据库来说是不推荐的,随着插入的压力增大,会在这张表的尾部 Region 形成热点,而且这个热点并没有办法分散到多台机器。TiDB 在 GA 的版本中会对非自增 ID 主键进行优化,让 insert workload 尽可能分散。

建议:
如果业务没有必要使用单调递增 ID 作为主键,就别用,使用真正有意义的列作为主键(一般来说,例如:邮箱、用户名等)

使用随机的 UUID 或者对单调递增的 ID 进行 bit-reverse (位反转)


json类型

Json 类型可以存储 Json 这种半结构化的数据,相比于直接将 Json 存储为字符串,它的好处在于:

使用 Binary 格式进行序列化,对 Json 的内部字段的查询、解析加快;
多了 Json 合法性验证的步骤,只有合法的 Json 文档才可以放入这个字段中;
Json 字段本身上,并不能创建索引。相反,可以对 Json 文档中的某个子字段创建索引。例如:

CREATE TABLE city (
    id INT PRIMARY KEY,
    detail JSON,
    population INT AS (JSON_EXTRACT(detail, '$.population')
);
INSERT INTO city VALUES (1, '{"name": "Beijing", "population": 100}');
SELECT id FROM city WHERE population >= 100;

不支持存储过程

TiDB 目前还不支持触发器、存储过程、自定义函数、外键,除此之外,TiDB 支持绝大部分 MySQL 5.7 的语法。

尝试创建存储过程会报错

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 15 near "PROCEDURE IF EXISTS count_t_pic_record"

TiDB部署

建议用 tiup 部署,k8s 搭建起来较复杂。


上一篇 Apache-JMeter

下一篇 MySQL-InnoDB 存储引擎

阅读
评论
2.5k
阅读预计9分钟
创建日期 2018-11-24
修改日期 2020-11-03
类别

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论