一、TiDB引入
1.1、数据库技术发展简史
数据库技术的形成过程和发展可分为如下三个阶段:
层次和网状数据库管理系统-可以理解为使用指针来表示数据之间的联系
关系数据库管理系统(RDBMS)-可以理解为理解为使用二维表来表示维护数据间的关系
新一代数据库技术的研究和发展-针对关系型数据库存在数据模型,性能,扩展性,伸缩性等方面的缺点,出现了:
- ORDBMS:面向对象数据库技术。如:PostGreSQL
- NoSQL:非结构化数据库技术。如:键值存储数据库:Redis;列式储数数据库:HBase;文档型数据库:MongoDB;图形数据库:Neo4J
NewSQL:这类数据库不仅具有NoSQL对海量数据的存储管理能力,还保持了传统数据库支持ACID和SQL等特性。如:TiDB
1.2、从MySQL到TiDB
1.2.1 场景引入
假设现在有一个核心业务库MySQL的数据量已经近亿行,且还在不断增长中,所有数据要求多副本保存至少5年,且除了有对历史数据进行统计分析的离线报表业务外,还有一些针对用户数据实时查询的需求,如用户历史订单实时查询
1.2.2 问题分析
MySQL能否满足上述场景需求?
根据以往的MySQL使用经验,MySQL单表在 5000 万行以内时,性能较好,单表超过5000万行后,数据库性能、可维护性都会极剧下降。当然这时候可以做MySQL分库分表,如使用Mycat或Sharding-jdbc
分库分表的能否解决问题?
分库分表的优点非常明显,如:
将大表拆分成小表,单表数据量控制在 5000 万行以内,使 MySQL 性能稳定可控。
将单张大表拆分成小表后,能水平扩展,通过部署到多台服务器,提升整个集群的性能。
但是,此方案的缺点也非常明显:
分表跨实例后,产生分布式事务管理难题,一旦数据库服务器宕机,有事务不一致风险。
分表后,需要维护的对象呈指数增长(MySQL实例数、需要执行的 SQL 变更数量等)。
分表后,汇总查询等跨分片场景较难实现
1.2.3 问题解决
基于以上核心痛点,调研市场上的各大数据库,我们可以考虑选用NewSQL技术来解决,因为NewSQL技术有如下显著特点:
- 无限水平扩展能力
- 分布式强一致性,确保数据 100% 安全
- 完整的分布式事务处理能力与 ACID 特性
而TiDB数据库 GitHub的活跃度及社区贡献者方面都可以算得上是国际化的开源项目,是NewSQL技术中的代表性产品,所以我们可以选择使用TiDB数据库!
1.3、TiDB概述
1.3.1 官网
https://pingcap.com/index.html
TiDB可以理解为是MySQL的加强版/分布式MySQL/MySQLPlus
1.3.2 简介
TiDB 是 PingCAP 公司设计的开源分布式 HTAP (Hybrid Transactional and Analytical Processing) 数据库,结合了传统的 RDBMS 和 NoSQL 的最佳特性。TiDB 兼容 MySQL,支持无限的水平扩展,具备强一致性和高可用性。TiDB 的目标是为 OLTP (Online Transactional Processing) 和 OLAP (Online Analytical Processing) 场景提供一站式的解决方案。
TiDB 的设计目标是 100% 的 OLTP 场景和 80% 的 OLAP 场景,更复杂的 OLAP 分析可以通过 TiSpark 项目来完成。
TiDB 对业务没有任何侵入性,能优雅的替换传统的数据库中间件、数据库分库分表等 Sharding 方案。同时它也让开发运维人员不用关注数据库 Scale 的细节问题,专注于业务开发,极大的提升研发的生产力。
1.3.3 OLTP和OLAP
- OLTP 在线事务处理。强调支持短时间内大量并发的事务操作(增删改查)能力,每个操作涉及的数据量都很小(比如几十到几百字节)。强调事务的强一致性(想想银行转账交易,容不得差错)
- OLAP 在线分析处理。偏向于复杂的只读查询,读取海量数据进行分析计算,查询时间往往很长。举例:“双十一”结束,淘宝的运营人员对订单进行分析挖掘,找出一些市场规律等等。 这种分析可能需要读取所有的历史订单进行计算,耗时几十秒甚至几十分钟都有可能。
二、TiDB架构特性
2.1、TiDB 整体架构
TiDB 集群主要包括三个核心组件:TiDB Server,PD Server 和 TiKV Server此外,还有用于解决用户复杂 OLAP 需求的TiSpark 组件和简化云上部署管理的TiDB Operator 组件。
以一条插入数据的SQL语句为例,SQL到达TiDB Cluster后,会先请求PD Cluster拿到TSO(事务操作时间戳),同样请求PD Cluster拿到数据要存入到TIKV Cluster的哪个位置,即图上的Data Location,然后将数据组长成Key-Value的形式,存入到TIKV Cluster上面。注意,保存在TIKV Cluster上面的数据为了数据安全会形成多副本,写入数据的时候会写入其中一个TIKV Cluster的region,它就是leader身份,然后leader向其他follower同步数据。leader与follower之间有心跳检测,如果检测到leader心跳消失了,follower就会重新推选leader
2.1.1 TiDB Cluster
TiDB Cluster负责接收 SQL 请求,处理 SQL 相关的逻辑,并通过 PD 找到存储计算所需数据的 TiKV 地址,与 TiKV 交互获取数据,最终返回结果。TiDB Server 是无状态的,其本身并不存储数据,只负责计算,可以无限水平扩展,可以通过负载均衡组件(如LVS、HAProxy 或 F5)对外提供统一的接入地址。
2.1.2 PD Cluster
Placement Driver (简称 PD) 是整个集群的管理模块(大脑),其主要工作有三个:一是存储集群的元信息(某个 Key 存储在哪个 TiKV 节点);二是对 TiKV 集群进行调度和负载均衡;三是分配全局唯一且递增的事务 ID。
上图画了三个PD Cluster,有一个是leader,另外两个是follower
2.1.3 TiKV Cluster
TiKV Server 负责存储数据,从外部看 TiKV 是一个分布式的提供事务的 Key-Value 存储引擎。
2.1.4 region的作用
TiKV Map是一个非常大的Map,里面存储了所有的key-value键值对。数据会先写入TiKV Map,然后写入TiKV Cluster,通常是先写入Leader,然后由Leader向Follower进行数据同步。如果是来一条数据就做一次同步,就会非常频繁显然效率是不高的。如果是将TiKV Map进行同步,它太大了也不合适。
于是,region就出现了,它的默认大小是96M。Leader和Follower进行同步的单位就是region。TiKV Map会根据字节的顺序进行排序,划分到不同的region。
2.1.5 分布式SQL的执行逻辑
现在要从t1表里面查询category_id为1的数据条数。category_id为1的数据会分布到多个TiKV上面。首先会从每个TiKV上面读取行数据,然后进行过滤和求和。然后将求和结果上传给TiDB进行最终的求和。
2.1.6 TiSpark
TiSpark 作为 TiDB 中解决用户复杂 OLAP 需求的主要组件,将 Spark SQL 直接运行在 TiDB 存储层上,同时融合 TiKV 分布式集群的优势,并融入大数据社区生态。至此,TiDB 可以通过一套系统,同时支持 OLTP 与 OLAP,免除用户数据同步的烦恼。
2.1.7 TiDB Operator
TiDB Operator 提供在主流云基础设施(Kubernetes)上部署管理 TiDB 集群的能力。它结合云原生社区的容器编排最佳实践与 TiDB 的专业运维知识,集成一键部署、多集群混部、自动运维、故障自愈等能力,极大地降低了用户使用和管理 TiDB 的门槛与成本。
2.1.8 与传统数据库的对比
TiDB的强项不在于轻量的简单SQL的响应速度。对于这种场景,传统数据库的性能已经很好了,如果使用TiDB,由于它分了TiDB Server、TiKV Server、PD Server,它们之间要进行网络通信,效率肯定是不如传统数据库的。
TiDB的强项在于大量高并发SQL的吞吐。
横向扩展
传统的关系型数据库使用分库分表。以上图的水平分片为例,使用Sharding-JDBC将一张客户表根据主键拆分(比如说,根据主键与数据库实例取模)到多个数据库多张表下面,这样一张大表的数据就被打散到多张表,查询效率就会提高。但是,如果要根据主键进行范围查询,那这种需求数据库层面是没法实现的,就需要在应用层面指定这一次查询要查询哪个数据库,这无疑会带来开发维护成本。
TiDB天生就解决了上面的问题。数据是存到了TiKV的region,region就像分片策略的一个分片单位,解决了分片的问题。在查询时,不需要在业务层面做特别的定制,TiDB会向PD Server询问这些数据在哪个region下面。
2.2 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 的水平扩展,按需扩展吞吐或存储,轻松应对高并发、海量数据场景。
真正金融级高可用
相比于传统主从 (M-S) 复制方案,基于 Raft 的多数派选举协议可以提供金融级的 100% 数据强一致性保证,且在不丢失大多数副本的前提下,可以实现故障的自动恢复 (auto-failover),无需人工介入。
2.2.1 水平扩展
无限水平扩展是 TiDB 的一大特点,这里说的水平扩展包括两方面:计算能力(TiDB)和存储能力(TiKV)。
TiDB Server 负责处理 SQL 请求,随着业务的增长,可以简单的添加 TiDB Server 节点,提高整体的处理能力,提供更高的吞吐。
TiKV 负责存储数据,随着数据量的增长,可以部署更多的 TiKV Server 节点解决数据 Scale 的问题。
PD 会在 TiKV 节点之间以 Region 为单位做调度,将部分数据迁移到新加的节点上。
所以在业务的早期,可以只部署少量的服务实例(推荐至少部署 3 个 TiKV, 3 个 PD,2 个 TiDB),随着业务量的增长,按照需求添加 TiKV 或者 TiDB 实例。
2.2.2 高可用
高可用是 TiDB 的另一大特点,TiDB/TiKV/PD 这三个组件都能容忍部分实例失效,不影响整个集群的可用性。下面分别说明这三个组件的可用性、单个实例失效后的后果以及如何恢复。
1、TiDB
TiDB 是无状态的,推荐至少部署两个实例,前端通过负载均衡组件对外提供服务。当单个实例失效时,会影响正在这个实例上进行的 Session,从应用的角度看,会出现单次请求失败的情况,重新连接后即可继续获得服务。单个实例失效后,可以重启这个实例或者部署一个新的实例。
2、PD
PD 是一个集群,通过 Raft 协议保持数据的一致性,单个实例失效时,如果这个实例不是 Raft 的 leader,那么服务完全不受影响;如果这个实例是 Raft 的 leader,会重新选出新的 Raft leader,自动恢复服务。PD 在选举的过程中无法对外提供服务,这个时间大约是3秒钟。推荐至少部署三个 PD 实例,单个实例失效后,重启这个实例或者添加新的实例。
3、TiKV
TiKV 是一个集群,通过 Raft 协议保持数据的一致性(副本数量可配置,默认保存三副本),并通过 PD 做负载均衡调度。单个节点失效时,会影响这个节点上存储的所有 Region。对于 Region 中的 Leader 节点,会中断服务,等待重新选举;对于 Region 中的 Follower 节点,不会影响服务。当某个 TiKV 节点失效,并且在一段时间内(默认 30 分钟)无法恢复,PD 会将其上的数据迁移到其他的 TiKV 节点上。
2.2.3 TiDB 存储和计算能力
2.2.3.1 存储能力-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+树叶子节点膨胀带来的大量随机读写。从何提升了整体的吞吐量。
2.2.3.2 计算能力-TiDB Server
TiDB Server本身是无状态的,意味着当计算能力成为瓶颈的时候,可以直接扩容机器,对用户是透明的。理论上TiDB Server的数量并没有上限限制。
三、TiDB安装部署
https://pingcap.com/docs-cn/stable/overview/#部署方式
3.1 TiDB-Local单机版
1、下载安装包
wgethttp://download.pingcap.org/tidb-latest-linux-amd64.tar.gz2、解压文件
tar-zxvftidb-latest-linux-amd64.tar.gz-C/usr/local/src/tidb/3、启动
cd/usr/local/src/tidb/tidb-latest-linux-amd64#启动PD./bin/pd-server --data-dir=pd --log-file=pd.log&#启动tikv./bin/tikv-server--pd="127.0.0.1:2379"--data-dir=tikv --log-file=tikv.log&#启动tidb-server./bin/tidb-server--store=tikv--path="127.0.0.1:2379"--log-file=tidb.log&4、登录
mysql-h192.168.52.111-P4000-u root3.2 TiDB-Docker集群版
略
四、快速开始
4.1 没有主键的表如何存数据
如上图,由1.3节,我们知道一条数据会映射为TiDB的key-value格式,value就是数组的内容,而key的格式是t[tid]_r[主键id]。如果这个表就没有主键,那key是什么呢?
对于没有主键的表,tidb会给一个隐藏字段_tidb_rowid作为表的ID
4.2 聚簇索引和非聚簇索引
传统关系型数据库:
- 聚簇索引:主键就是聚簇索引,索引和数据保存在一起
- 非聚簇索引:索引和数据分开存
TiDB
- 聚簇索引:TiDB的数据是存储在TiKV上面,格式是key-value,聚簇索引可以理解为主键就对应这里的key
- 非聚簇索引:主键不直接直接对应数据,而是主键对应rowid,rowid再指向数据
TiDB的主键具有如下约束:
- 唯一标识表中的行
- 不允许为NULL
- 每个表只允许一个主键
- 如果声明的主键不是INTEGER数据类型,TiDB会字段为表创建非聚簇索引
- 如果没有声明主键,TiDB会为表创建一个隐式主键
_tidb_rowid
即主键不一定是聚簇索引
五、Java连接TiDB
和连接MySQL类似,略。
六、TiDB技术内幕
6.1 Key-Value
作为保存数据的系统,首先要决定的是数据的存储模型,也就是数据以什么样的形式保存下来。TiKV 的选择是 Key-Value 模型,并且提供有序遍历方法。简单来讲,可以将 TiKV 看做一个巨大的 Map,其中 Key 和 Value 都是原始的 Byte 数组,在这个 Map 中,Key 按照 Byte 数组中的原始二进制比特位比较顺序排列。
- 这是一个巨大的 Map,也就是存储的是 Key-Value pair
- 这个 Map 中的 Key-Value pair 按照 Key 的二进制顺序有序,也就是我们可以 Seek 到某一个 Key 的位置,然后不断的调用 Next 方法以递增的顺序获取比这个 Key 大的 Key-Value
6.2 RocksDB
任何持久化的存储引擎,数据终归要保存在磁盘上,TiKV 也不例外。但是 TiKV 没有选择直接向磁盘上写数据,而是把数据保存在 RocksDB 中,具体的数据落地由 RocksDB 负责。
6.3 Raft
我们需要想办法把数据复制到多台机器上,这样一台机器挂了,我们还有其他的机器上的副本;复杂来说,我们还需要这个复制方案是可靠、高效并且能处理副本失效的情况。听上去比较难,但是好在我们有 Raft 协议。
6.4 Region
对于一个 KV 系统,将数据分散在多台机器上有两种比较典型的方案:一种是按照 Key 做 Hash,根据 Hash 值选择对应的存储节点;另一种是分 Range,某一段连续的 Key 都保存在一个存储节点上。TiKV 选择了第二种方式,将整个 Key-Value 空间分成很多段,每一段是一系列连续的 Key,我们将每一段叫做一个Region,并且我们会尽量保持每个 Region 中保存的数据不超过一定的大小(这个大小可以配置,目前默认是 64mb)。每一个 Region 都可以用 StartKey 到 EndKey 这样一个左闭右开区间来描述。
6.5 MVCC
很多数据库都会实现多版本控制(MVCC),TiKV 也不例外。
6.6 事务
TiKV 的事务采用乐观锁