[From] http://kuaibao.qq.com/s/20180510G0UFL000?refer=cp_1026mysql
最近TiDB掀起了一波分布式数据库的热潮,公司也在着手准备TiDB的落地工做,前几天也参与了几场公司针对TiDB的分享会,下面咱们了解一下关于TiDB。web
TiDB 是什么?sql
TiDB 是一个分布式 NewSQL 数据库。它支持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和 MySQL 协议,具备数据强一致的高可用特性,是一个不只适合 OLTP 场景还适合 OLAP 场景的混合数据库。数据库
TiDB怎么来的?编程
著名的开源分布式缓存服务 Codis 的做者,PingCAP联合创始人& CTO ,资深 infrastructure 工程师的黄东旭,擅长分布式存储系统的设计与实现,开源狂热分子的技术大神级别人物。即便在互联网如此繁荣的今天,在数据库这片边界模糊且不肯定地带,他还在努力寻找肯定性的实践方向。缓存
直到 2012 年末,他看到 Google 发布的两篇论文,如同棱镜般,折射出他本身心里微烁的光彩。这两篇论文描述了 Google 内部使用的一个海量关系型数据库 F1/Spanner ,解决了关系型数据库、弹性扩展以及全球分布的问题,并在生产中大规模使用。“若是这个能实现,对数据存储领域来讲将是颠覆性的”,黄东旭为完美方案的出现而兴奋, PingCAP 的 TiDB 在此基础上诞生了。安全
TiDB架构网络
TiDB在总体架构基本是参考 Google Spanner 和 F1 的设计,上分两层为TiDB和TiKV。 TiDB 对应的是 Google F1, 是一层无状态的 SQL Layer ,兼容绝大多数 MySQL 语法,对外暴露 MySQL 网络协议,负责解析用户的 SQL 语句,生成分布式的 Query Plan,翻译成底层 Key Value 操做发送给 TiKV , TiKV 是真正的存储数据的地方,对应的是 Google Spanner ,是一个分布式 Key Value 数据库,支持弹性水平扩展,自动的灾难恢复和故障转移(高可用),以及 ACID 跨行事务。值得一提的是 TiKV 并不像 HBase 或者 BigTable 那样依赖底层的分布式文件系统,在性能和灵活性上能更好,这个对于在线业务来讲是很是重要。架构
▲ TiDB 总体架构并发
因此一套集群是又这样的3类角色共同组建而成。每一个部分的解释以下:
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 是一个集群,须要部署奇数个节点,通常线上推荐至少部署 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 为单位进行调度。 固然作这件事情,我是认真的,而不是简单试一下就完事了。我列了一个基本的计划,来看看是否可以知足一些痛点,改进一些状况。
TiDB开发语言
在 TiDB 研发语言的选择过程当中,放弃了 Java 而采用 Go 。TiDB整个项目分为两层,TiDB 做为 SQL 层,采用 Go 语言开发, TiKV 做为下边的分布式存储引擎,采用 Rust 语言开发。在架构上确实相似 FoundationDB,也是基于两层的结构。 FoundationDB 的 SQL Layer 采用 Java ,底层是 C++ ,不过在去年,被 Apple 收购了。 在选择编程语言并无融入太多的我的喜爱偏向, SQL 层选择 Go 相对 Java 来讲:
第一是 他们团队的背景使用 Go 的开发效率更高,并且性能尚可,尤为对于高并发程序而言,可使用 goroutine / channel 等工具用更少的代码写出正确的程序;
第二是 在标准库中不少包对网络程序开发很是友好,这个对于一个分布式系统来讲很是重要;
第三是 在存储引擎底层对于性能要求很高,Go 毕竟是一个带有 GC 和 Runtime 的语言,在 TiKV 层能够选择的方案并很少,过去基本只有 C 或 C++,不过近两年随着 Rust 语言的成熟,又在通过长时间的思考和大量实验,最终他们团队选择了 Rust( Rust是Mozilla开发的注重安全、性能和并发性的编程语言。“Rust”,由web语言的领军人物Brendan Eich(js之父),Dave Herman以及Mozilla公司的Graydon Hoare 协力开发。)。
TiDB 对比 NOSQL
TiDB 对于这些 NoSQL 来讲,最大的特色是编程接口是 SQL,SQL对于开发者而言是更加灵活的操做数据库的方式,且对 MySQL 有着极高的兼容性—原业务的 MySQL切换到 TiDB 几乎一行代码都不用修改就能够完成。TiDB 在支持 SQL 的同时有没有丧失 HBase 这样的系统的弹性扩展能力,业务层不须要再去关心数据库的容量,不用去考虑分库分表,也不用像过去那样投入很大的运维力量,扩容只需简单加机器就好,存储节点故障对业务透明,并且数据库自己具备自我修复的能力,保证数据不会丢失。 对于 MongoDB 也是同样,更重要的是不须要改变用户已有的习惯和程序,并且为了定义将来的云上的数据库形态,TiDB 设计的目标是单集群须要能够 Scale 到 1000 以上物理节点的规模,支持 P 级别容量,万亿以上的行的结构化数据存储,在这个前提约束下的设计和技术选型和 MongoDB 很不同,在大数据量的状况下 TiDB 的表现更稳定,扩展更加平滑。 TiDB 的 SQL 优化器是黄东旭他们从头开始实现的一个面向分布式存储设计的查询优化器,使用了不少学术界很新的查询优化技术和分布式计算框架的思想,保证 MySQL 兼容性的前提下比 MySQL 在复杂查询下表现要好得多。
TiDB 支持包括跨行事务,JOIN 及子查询在内的绝大多数 MySQL 的语法,用户能够直接使用现有的 MySQL 客户端链接。若是现有的业务已经基于 MySQL 开发,大多数状况不须要修改代码便可直接替换单机的 MySQL。
包括现有的大多数 MySQL 运维工具(如 PHPMyAdmin, Navicat, MySQL Workbench 等),以及备份恢复工具(如 mysqldump, mydumper/myloader)等均可以直接使用。
不过一些特性因为在分布式环境下无法很好的实现,目前暂时不支持或者是表现与 MySQL 有差别。
一些 MySQL 语法在 TiDB 中能够解析经过,可是不会作任何后续的处理,例如 Create Table 语句中 Engine 以及 Partition 选项,都是解析并忽略。更多兼容性差别请参考具体的文档。
存储过程
视图
触发器
自定义函数
外键约束
全文索引
空间索引
非 UTF8 字符集
下面具体介绍 TiDB 中基本的增删改查操做。
使用 CREATE DATABASE 语句建立数据库。语法以下: CREATE DATABASE db_name [options]; 例如,要建立一个名为 samp_db 的数据库,可以使用如下语句: CREATE DATABASE IF NOT EXISTS samp_db; 使用 SHOW DATABASES 语句查看数据库: SHOW DATABASES; 使用 DROP DATABASE 语句删除数据库,例如: DROP DATABASE samp_db;
使用 CREATE TABLE 语句建立表。语法以下: CREATE TABLE table_name column_name data_type constraint; 例如: CREATE TABLE person ( number INT(11), name VARCHAR(255), birthday DATE ); 若是表已存在,添加 IF NOT EXISTS 可防止发生错误: CREATE TABLE IF NOT EXISTS person ( number INT(11), name VARCHAR(255), birthday DATE ); 使用 SHOW CREATE 语句查看建表语句。例如: SHOW CREATE table person; 使用 SHOW FULL COLUMNS 语句查看表的列。 例如: SHOW FULL COLUMNS FROM person; 使用 DROP TABLE 语句删除表。例如: DROP TABLE person; 或者 DROP TABLE IF EXISTS person; 使用 SHOW TABLES 语句查看数据库中的全部表。例如: SHOW TABLES FROM samp_db;
对于值不惟一的列,可以使用 CREATE INDEX 或 ALTER TABLE 语句。例如: CREATE INDEX person_num ON person (number); 或者 ALTER TABLE person ADD INDEX person_num (number); 对于值惟一的列,能够建立惟一索引。例如: CREATE UNIQUE INDEX person_num ON person (number); 或者 ALTER TABLE person ADD UNIQUE person_num on (number); 使用 SHOW INDEX 语句查看表内全部索引: SHOW INDEX from person; 使用 ALTER TABLE 或 DROP INDEX 语句来删除索引。与 CREATE INDEX 语句相似,DROP INDEX 也能够嵌入 ALTER TABLE 语句。例如: DROP INDEX person_num ON person; ALTER TABLE person DROP INDEX person_num;
使用 INSERT 语句向表内插入数据。例如: INSERT INTO person VALUES("1","tom","20170912"); 使用 SELECT 语句检索表内数据。例如: SELECT * FROM person; +--------+------+------------+ | number | name | birthday |+--------+------+------------+ | 1 | tom | 2017-09-12 |+--------+------+------------+ 使用 UPDATE 语句修改表内数据。例如: UPDATE person SET birthday='20171010' WHERE name='tom'; SELECT * FROM person; +--------+------+------------+ | number | name | birthday |+--------+------+------------+ | 1 | tom | 2017-10-10 |+--------+------+------------+ 使用 DELETE 语句删除表内数据: DELETE FROM person WHERE number=1; SELECT * FROM person; Empty set (0.00 sec)
使用 CREATE USER 语句建立一个用户 tiuser,密码为 123456: CREATE USER 'tiuser'@'localhost' IDENTIFIED BY '123456'; 受权用户 tiuser 可检索数据库 samp_db 内的表: GRANT SELECT ON samp_db.* TO 'tiuser'@'localhost'; 查询用户 tiuser 的权限: SHOW GRANTS for tiuser@localhost; 删除用户 tiuser: DROP USER 'tiuser'@'localhost';