简介
TiDB 是 PingCAP 公司受 Google Spanner / F1 论文启发而设计的开源分布式 HTAP (Hybrid Transactional and Analytical Processing) 数据库,结合了传统的 RDBMS 和 NoSQL 的最佳特性。TiDB 兼容 MySQL,支持无限的水平扩展,具备强一致性和高可用性。TiDB 的目标是为 OLTP (Online Transactional Processing) 和 OLAP (Online Analytical Processing) 场景提供一站式的解决方案。
特性
1)高度兼容 MySQL
大多数情况下,无需修改代码即可从 MySQL 轻松迁移至 TiDB,分库分表后的 MySQL 集群亦可通过 TiDB 工具进行实时迁移。
2)水平弹性扩展
通过简单地增加新节点即可实现 TiDB 的水平扩展,按需扩展吞吐或存储,轻松应对高并发、海量数据场景。
3)分布式事务
TiDB 100% 支持标准的 ACID 事务。
4)真正金融级高可用
相比于传统主从 (M-S) 复制方案,基于 Raft 的多数派选举协议可以提供金融级的 100% 数据强一致性保证,且在不丢失大多数副本的前提下,可以实现故障的自动恢复 (auto-failover),无需人工介入。
5)一站式 HTAP 解决方案
TiDB 作为典型的 OLTP 行存数据库,同时兼具强大的 OLAP 性能,配合 TiSpark,可提供一站式 HTAP 解决方案,一份存储同时处理 OLTP & OLAP,无需传统繁琐的 ETL 过程。
6)云原生 SQL 数据库
TiDB 是为云而设计的数据库,同 Kubernetes 深度耦合,支持公有云、私有云和混合云,使部署、配置和维护变得十分简单。
兼容性
不支持的特性:视图、存储过程、触发器、自定义函数、外键约束、全文索引、空间索引、非UTF-8字符集。与我们实际应用不冲突。
与Mysql差异
1)TiDB 的自增 ID (Auto Increment ID) 只保证自增且唯一,并不保证连续分配。TiDB 目前采用批量分配的方式,所以如果在多台 TiDB 上同时插入数据,分配的自增 ID 会不连续
2)TiDB 支持常用的 MySQL 内建函数,但是不是所有的函数都已经支持,具体请参考语法文档
3)TiDB 实现了 F1 的异步 Schema 变更算法,DDL 执行过程中不会阻塞线上的 DML 操作。目前支持的DDL包括数据库、表、索引、列的创建和删除操作以及列的修改操作。TiDB对列的修改有限制,如不支持从null改成not null,不支持对enum列修改等
事务
TiDB 使用乐观事务模型,在执行 Update、Insert、Delete 等语句时,只有在提交过程中才会检查写写冲突,而不是像 MySQL 一样使用行锁来避免写写冲突。所以业务端在执行 SQL 语句后,需要注意检查 commit 的返回值,即使执行时没有出错,commit的时候也可能会出错。
文档
在使用TiDB时,可以参照官方文档进行查阅,地址:https://www.pingcap.com/docs-cn/
架构
1)TiDB Server
TiDB Server 负责接收 SQL 请求,处理 SQL 相关的逻辑,并通过 PD 找到存储计算所需数据的 TiKV 地址,与 TiKV 交互获取数据,最终返回结果。 TiDB Server 是无状态的,其本身并不存储数据,只负责计算,可以无限水平扩展,可以通过负载均衡组件(如LVS、HAProxy 或 F5)对外提供统一的接入地址
2)Placement Driver
Placement Driver (简称 PD) 是整个集群的管理模块,其主要工作有三个: 一是存储集群的元信息(某个 Key 存储在哪个 TiKV 节点);二是对 TiKV 集群进行调度和负载均衡(如数据的迁移、Raft group leader 的迁移等);三是分配全局唯一且递增的事务 ID。PD 是一个集群,需要部署奇数个节点,一般线上推荐至少部署 3 个节点
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 为单位进行调度
解决问题
1)水平扩展
无限水平扩展是 TiDB 的一大特点,这里说的水平扩展包括两方面:计算能力和存储能力。TiDB Server 负责处理 SQL 请求,随着业务的增长,可以简单的添加 TiDB Server 节点,提高整体的处理能力,提供更高的吞吐。TiKV 负责存储数据,随着数据量的增长,可以部署更多的 TiKV Server 节点解决数据量的问题(自动分库)。PD 会在 TiKV 节点之间以 Region 为单位做调度,将部分数据迁移到新加的节点上。所以在业务的早期,可以只部署少量的服务实例(推荐至少部署 3 个 TiKV, 3 个 PD,2 个 TiDB),随着业务量的增长,按照需求添加 TiKV 或者 TiDB 实例
2)高可用
高可用是 TiDB 的另一大特点,TiDB/TiKV/PD 这三个组件都能容忍部分实例失效,不影响整个集群的可用性。下面分别说明这三个组件的可用性、单个实例失效后的后果以及如何恢复。
TiDB 是无状态的,推荐至少部署两个实例,前端通过负载均衡组件对外提供服务。当单个实例失效时,会影响正在这个实例上进行的 Session,从应用的角度看,会出现单次请求失败的情况,重新连接后即可继续获得服务。单个实例失效后,可以重启这个实例或者部署一个新的实例。
PD 是一个集群,通过 Raft 协议保持数据的一致性,单个实例失效时,如果这个实例不是 Raft 的 leader,那么服务完全不受影响;如果这个实例是 Raft 的 leader,会重新选出新的 Raft leader,自动恢复服务。PD 在选举的过程中无法对外提供服务,这个时间大约是3秒钟。推荐至少部署三个 PD 实例,单个实例失效后,重启这个实例或者添加新的实例。
TiKV 是一个集群,通过 Raft 协议保持数据的一致性(副本数量可配置,默认保存三副本),并通过 PD 做负载均衡调度。单个节点失效时,会影响这个节点上存储的所有 Region。对于 Region 中的 Leader 结点,会中断服务,等待重新选举;对于 Region 中的 Follower 节点,不会影响服务。当某个 TiKV 节点失效,并且在一段时间内(默认 10 分钟)无法恢复,PD 会将其上的数据迁移到其他的 TiKV 节点上。
3)小彩蛋
兼容 MySQL 5.7 及以上,同时更好地支持文档类型存储,表中包含一个 JSON 字段来存储复杂的信息
插入JSON数据
查询JSON数据,和 MongoDB 等文档数据库相同,可以在服务端支持用户各种复杂组合查询条件
除了插入、查询外,对 JSON 的修改也是支持的。目前支持的 MySQL 5.7 的 JSON 函数:JSON_EXTRACT、JSON_ARRAY、JSON_OBJECT、JSON_SET、JSON_REPLACE、JSON_INSERT、JSON_REMOVE、JSON_TYPE、JSON_UNQUOTE
软硬件要求
参照:https://www.pingcap.com/docs-cn/op-guide/recommendation/
安装
由于服务器数量个数限制,这里采用单台安装测试,具体安装步骤如下:
1)下载官方Binary压缩包,wget http://download.pingcap.org/tidb-latest-linux-amd64.tar.gz,wget http://download.pingcap.org/tidb-latest-linux-amd64.sha256
2)检查文件完整性,sha256sum -c tidb-latest-linux-amd64.sha256
3)解压文件,tar -xzf tidb-latest-linux-amd64.tar.gz && cd tidb-latest-linux-amd64
启动
1)启动pd-server,./bin/pd-server --data-dir=pd
2)启动tikv-server,./bin/tikv-server --pd="127.0.0.1:2379" -store=tikv
3)启动tidb-server,./bin/tidb-server --store=tikv --path="127.0.0.1:2379"
注:此三项启动顺序不能变更
连接
启动成功后,可以通过Navicat等工具连接,TiDB对外的连接方式与Mysql一样,对于用户来说,根本感受不到使用的是TiDB还是Mysql。这里需要设置一下Centos的防火墙,Centos7防火墙的设置与Centos6不同,可以关闭防火墙或者开放端口
1)关闭防火墙
systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall开机启动
两者可以同时使用,避免每次重启都得重新关闭防火墙
2)开放端口
firewall-cmd --zone=public --add-port=4000/tcp --permanent #开放4000端口
firewall-cmd --reload #重新加载防火墙配置,此时4000端口才真正的开放
其他功能可以使用firewall-cmd --help查看
**开始
**
1)创建表
CREATE TABLE `test_user` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(32) NOT NULL COMMENT '名字',
`age` tinyint(3) UNSIGNED DEFAULT NULL COMMENT '年纪',
`summary` json DEFAULT NULL COMMENT '简介',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=30001 COMMENT='测试用户表';
2)数据库连接
连接池依然使用原有的com.alibaba.druid.pool.DruidDataSource,不需要修改原有任何类,只需要修改数据库连接地址及端口等配置信息即可
jdbc.url=jdbc:mysql://192.168.32.129:4000/test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
jdbc.username=root
jdbc.password=
druid.timeBetweenEvictionRunsMillis=60000
druid.minEvictableIdleTimeMillis=300000
druid.maxActive=60
druid.initialSize=2
druid.maxWait=200
druid.minIdle=30
druid.maxOpenPreparedStatements=30
3)用例测试
进行了简单的CURD操作,都可以满足,尝试了一下JSON数据的查询,可以准确的查询到结果,后期可以进行压力测试,甚至代替mongo
集群
由于TiDB的pd、tikv和tidb三部分都可以搭建集群,满足了高可用性,由于自己的虚拟机目前只有一台,暂未做测试,后续补上。
测试
1)基础功能测试
进行了简单的CURD操作,基本功能得以满足,对于mysql的函数及关键字的支持未测试
2)写入测试
为方便下面的查询测试,这里通过for循环为数据库添加了10万条数据,整个过程耗时18分钟,没有遇到错误,写入可用性不错
3)查询测试
这里以10万条数据做了简单的查询测试,由于目前只有单台服务,可能对实际结果有所偏差
条件
耗时(毫秒)
查询主键
82
查询普通索引列(varchar)
86
查询普通列(varchar)
505
查询JSON数据
729
总结
综上所述,TiDB可以满足mysql既有的功能需求,能够达到线上使用的要求,但线上若想使用TiDB,需要开发、运维和DBA协调,包括软硬件是否能够满足,DBA维护工作是否可行等等。