分布式数据库TIDB
- 第一章 绪论
- 研究背景
目前,在电商、金融、O2O、零售、电信等行业普遍存在用户基数大,营销活动频繁,核心交易系统响应日益变慢的问题,随着业务数据增长迅速,超过单机数据库的承受极限,制约业务的发展;在电力、气象、农业、智能制造等行业海量的数据远远超过单机数据库的承受极限。
常用的单机数据库的瓶颈包括:单个表数据量越大,读写锁,插入操作重新建立索引效率越低;单个库数据量太大(一个数据库数据量到1T-2T就是极限);单个数据库服务器压力过大;读写速度遇到瓶颈(并发量几百);
针对单机数据库的瓶颈问题,一般做法包括:分区、分表、分库等。
分区,就是把一张表的数据分成N个区块,在逻辑上看最终只是一张表,但底层是由N个物理区块组成的;分表,就是把一张表按一定的规则分解成N个具有独立存储空间的实体表,系统读写时需要根据定义好的规则得到对应的字表明,然后操作它。分库,就是将数据存放到不同的数据库中,可以按照垂直拆分和水平拆分及读写分离的原则,将数据划分到不同的数据库中,分库目的是是为了突破单节点数据库服务器的 I/O 能力限制,解决数据库扩展性问题。
对数据进行拆分之后面临一些新的问题包括:事务的支持;分库分表,就变成了分布式事务;进行join时跨库,跨表的问题;分库分表,读写分离使用了分布式,分布式为了保证强一致性,必然带来延迟,导致性能降低,系统的复杂度变高等。
针对以上问题,对于不同的方式之间没有严格的界限,特点不同,侧重点不同。需要根据实际情况,结合每种方式的特点来进行处理,另外还可以考虑选用第三方的数据库中间件(Atlas,Mycat,TDDL,DRDS,TIDB等),同时业务系统需要配合数据存储的升级。
本文主要讨论第三方的数据库中间件TIDB的原理、架构设计及使用。
-
- 研究现状
- mysql-proxy
- 研究现状
mysql-proxy是mysql官方提供的mysql中间件服务,上游可接入若干个mysql-client,后端可连接若干个mysql-server。
它使用mysql协议,任何使用mysql-client的上游无需修改任何代码,即可迁移至mysql-proxy上。
mysql-proxy最基本的用法,就是作为一个请求拦截,请求中转的中间层:
进一步的,mysql-proxy可以分析与修改请求。拦截查询和修改结果,需要通过编写Lua脚本来完成。
mysql-proxy允许用户指定Lua脚本对请求进行拦截,对请求进行分析与修改,它还允许用户指定Lua脚本对服务器的返回结果。
进行修改,加入一些结果集或者去除一些结果集均可。
mysql-proxy是一个官方提供的框架,具备良好的扩展性,可以用来完成:sql拦截与修改、性能分析与监控、读写分离、请求路由。
mysql主从同步延迟原理
mysql主从同步原理
mysql的主从复制都是单线程的操作,slave的Slave_IO_Running线程到主库取日志,效率比较高,DML,DDL的IO操作是随即的,slave上的其他查询产生 lock,由于 slave_sql_running是单线程的,所以一个 DDL卡住了,需求需求执行一段时间,所有之后的DDL会等待这个 DDL执行完才会继续执行,这就导致了延迟。
由于master可以并发,Slave_sql_running线程却不可以,所以主库执行 DDL需求一段时间,在slave执行相同的DDL时,就产生了延迟.
当主库的TPS并发较高时,产生的DDL数量超过Slave一个 sql线程所能承受的范围,那么延迟就产生了,当然还有就是可能与 slave的大型 query语句产生了锁等待。
通常处理延迟解决方案包括:1.业务的持久化层的实现采用分库架构,mysql服务可平行扩展分散压力;2.单个库读写分离,一主多从,主写从读,分散压力;3.服务的基础架构在业务和mysql之间加放 cache层;4.不同业务的mysql放在不同的机器;5.使用比主加更了的硬件设备作slave;5在硬件方面,采用好的服务器。
总之,mysql压力变小,延迟自然会变小。
-
-
- Atlas
-
Atlas是由 Qihoo 360,Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用Atlas运行mysql业务,每天承载的读写请求数达几十亿条。
Atlas是一个位于应用程序与MySQL之间,它实现了MySQL的客户端与服务端协议,作为服务端与应用程序通讯,同时作为客户端与MySQL通讯。它对应用程序屏蔽了DB的细节,同时为了降低MySQL负担,它还维护了连接池。
以下是一个可以参考的整体架构,LVS前端做负载均衡,两个Altas做HA,防止单点故障。
Altas的一些新特性:
1.主库宕机不影响读
主库宕机,Atlas自动将宕机的主库摘除,写操作会失败,读操作不受影响。从库宕机,Atlas自动将宕机的从库摘除,对应用没有影响。在mysql官方的proxy中主库宕机,从库亦不可用。
2.通过管理接口,简化管理工作,DB的上下线对应用完全透明,同时可以手动上下线。
3.自己实现读写分离
(1)为了解决读写分离存在写完马上就想读而这时可能存在主从同步延迟的情况,Altas中可以在SQL语句前增加 /*master*/ 就可以将读请求强制发往主库。
(2)如下图,主库可设置多项,用逗号分隔,从库可设置多项和权重,达到负载均衡。
4.自己实现分表
(1)需带有分表字段。
(2)支持SELECT、INSERT、UPDATE、DELETE、REPLACE语句。
(3)支持多个子表查询结果的合并和排序。
Atlas的分表功能比较薄弱,不能实现分布式分表,所有的子表必须在同一台DB的同一个database里且所有的子表必须事先建好,Atlas没有自动建表的功能。
5.官方主要功能逻辑由使用lua脚本编写,效率低,Atlas用C改写,QPS提高,latency降低。
6.安全方面的提升
(1)通过配置文件中的pwds参数进行连接Atlas的用户的权限控制。
(2)通过client-ips参数对有权限连接Atlas的ip进行过滤。
(3)日志中记录所有通过Altas处理的SQL语句,包括客户端IP、实际执行该语句的DB、执行成功与否、执行所耗费的时间 ,如下图4。
7.平滑重启
通过配置文件中设置lvs-ips参数实现平滑重启功能,否则重启Altas的瞬间那些SQL请求都会失败。该参数前面挂接的lvs的物理网卡的ip,注意不是虚ip。平滑重启的条件是至少有两台配置相同的Atlas且挂在lvs之后。
-
-
- Cobar
-
Cobar是阿里巴巴(B2B)部门开发的一种关系型数据的分布式处理系统,它可以在分布式的环境下看上去像传统数据库一样为您提供海量数据服务。
cobar中间件以proxy的形式位于前台应用和实际数据库之间,对前台的开放的接口是mysql通信协议。将前台SQL语句变更并按照数据分布规则转发到合适的后台数据分库,再合并返回结果,模拟单库下的数据库行为。
Cobar应用实例架构
应用介绍:
1.通过Cobar提供一个名为test的数据库,其中包含t1,t2两张表。后台有3个MySQL实例(ip:port)为其提供服务,分别为:A,B,C。
2.期望t1表的数据放置在实例A中,t2表的数据水平拆成四份并在实例B和C中各自放两份。t2表的数据要具备HA功能,即B或者C实例其中一个出现故障,不影响使用且可提供完整的数据服务
cabar优点总结:
1.数据和访问从集中式改变为分布:
Cobar支持将一张表水平拆分成多份分别放入不同的库来实现表的水平拆分;Cobar也支持将不同的表放入不同的库。多数情况下,用户会将以上两种方式混合使用。
注意:Cobar不支持将一张表,例如test表拆分成test_1,test_2, test_3.....放在同一个库中,必须将拆分后的表分别放入不同的库来实现分布式。
2.解决连接数过大的问题。
3.对业务代码侵入性少。
4.提供数据节点的failover,HA:
(1)Cobar的主备切换有两种触发方式,一种是用户手动触发,一种是Cobar的心跳语句检测到异常后自动触发。那么,当心跳检测到主机异常,切换到备机,如果主机恢复了,需要用户手动切回主机工作,Cobar不会在主机恢复时自动切换回主机,除非备机的心跳也返回异常。
(2)Cobar只检查MySQL主备异常,不关心主备之间的数据同步,因此用户需要在使用Cobar之前在MySQL主备上配置双向同步。
cobar缺点:
开源版本中数据库只支持mysql,并且不支持读写分离。
-
-
- Tddl
-
淘宝根据自己的业务特点开发了TDDL(Taobao Distributed Data Layer)框架,主要解决了分库分表对应用的透明化以及异构数据库之间的数据复制,它是一个基于集中式配置的jdbc datasource实现,具有主备,读写分离,动态数据库配置等功能。
TDDL通过数据访问层,部署在客户端的jar包,用于将用户的SQL路由到指定的数据库中。
淘宝很早就对数据进行过分库的处理,上层系统连接多个数据库,中间有一个叫做DBRoute的路由来对数据进行统一访问。
DBRoute对数据进行多库的操作、数据的整合,让上层系统像操作一个数据库一样操作多个库。
但是随着数据量的增长,对于库表的分法有了更高的要求,例如,你的商品数据到了百亿级别的时候,任何一个库都无法存放了,于是分成2个、4个、8个、16个、32个……直到1024个、2048个。
此时,数据查询的中间件就要能够承担查询重任,它对上层来说,必须像查询一个数据库一样来查询数据,还要像查询一个数据库一样快(每条查询在几毫秒内完成),TDDL就承担了这样一个工作。在外面有些系统也用DAL(数据访问层) 这个概念来命名这个中间件。下图展示了一个简单的分库分表数据查询策略。
主要优点:
1.数据库主备和动态切换;
2.带权重的读写分离;
3.单线程读重试;
4.集中式数据源信息管理和动态变更;
5.剥离的稳定jboss数据源;
6.支持mysql和oracle数据库;
7.基于jdbc规范,很容易扩展支持实现jdbc规范的数据源;
8.无server,client-jar形式存在,应用直连数据库;
9.读写次数,并发度流程控制,动态变更;
10.可分析的日志打印,日志流控,动态变更;
TDDL必须要依赖diamond配置中心,diamond是淘宝内部使用的一个管理持久配置的系统,目前淘宝内部绝大多数系统的配置,由diamond来进行统一管理,同时diamond也已开源。
TDDL复杂度相对较高,当前公布的文档较少,只开源动态数据源,分表分库部分还未开源,还需要依赖diamond,不推荐使用。
-
-
- Mycat分布式数据库
-
Mycat拦截了用户发送过来的SQL语句,首先对SQL语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL发往后端的真实数据库,并将返回的结果做适当的处理,最终再返回给用户。
上述图片里,Orders表被分为三个分片datanode(简称dn),这三个分片是分布在两台MySQL Server上(DataHost),即datanode=database@datahost方式,因此你可以用一台到N台服务器来分片,分片规则为(sharding rule)典型的字符串枚举分片规则,一个规则的定义是分片字段(sharding column)+分片函数(rule function),这里的分片字段为prov而分片函数为字符串枚举方式。
当Mycat收到一个SQL时,会先解析这个SQL,查找涉及到的表,然后看此表的定义,如果有分片规则,则获取到SQL里分片字段的值,并匹配分片函数,得到该SQL对应的分片列表,然后将SQL发往这些分片去执行,最后收集和处理所有分片返回的结果数据,并输出到客户端。
以select * from Orders where prov=?语句为例,查到prov=wuhan,按照分片函数,wuhan返回dn1,于是SQL就发给了MySQL1,去取DB1上的查询结果,并返回给用户。如果上述SQL改为select * from Orders where prov in (‘wuhan’,‘beijing’),那么,SQL就会发给MySQL1与MySQL2去执行,然后结果集合并后输出给用户。
通常业务中我们的SQL会有Order By 以及Limit翻页语法,此时就涉及到结果集在Mycat端的二次处理,这部分的代码也比较复杂,而最复杂的则属两个表的Jion问题,为此,Mycat提出了创新性的ER分片、全局表、HBT(Human Brain Tech)人工智能的Catlet、以及结合Storm/Spark引擎等十八般武艺的解决办法,从而成为目前业界最强大的方案。
Mycat发展到现在,适用的场景已经很丰富,而且不断有新用户给出新的创新性的方案,以下是几个典型的应用场景:
1、单纯的读写分离,此时配置最为简单,支持读写分离,主从切换,分表分库,对于超过1000万的表进行分片,最大支持1000亿的单表分片。
2、多租户应用,每个应用一个库,但应用程序只连接Mycat,从而不改造程序本身,实现多租户化报表系统,借助于Mycat的分表能力,处理大规模报表的统计替代Hbase,分析大数据作为海量数据实时查询的一种简单有效方案,比如100亿条频繁查询的记录需要在3秒内查询出来结果,除了基于主键的查询,还可能存在范围查询或其他属性查询,此时Mycat可能是最简单有效的选择。
Mycat长期路线图
强化分布式数据库中间件的方面的功能,使之具备丰富的插件、强大的数据库智能优化功能、全面的系统监控能力、以及方便的数据运维工具,实现在线数据扩容、迁移等高级功能,进一步挺进大数据计算领域,深度结合Spark Stream和Storm等分布式实时流引擎,能够完成快速的巨表关联、排序、分组聚合等 OLAP方向的能力,并集成一些热门常用的实时分析算法,让工程师以及DBA们更容易用Mycat实现一些高级数据分析处理功能。不断强化Mycat开源社区的技术水平,吸引更多的IT技术专家,使得Mycat社区成为中国的Apache,并将Mycat推到Apache基金会,成为国内顶尖开源项目,最终能够让一部分志愿者成为专职的Mycat开发者,荣耀跟实力一起提升。依托Mycat社区,聚集100个CXO级别的精英,众筹建设亲亲山庄,Mycat社区+亲亲山庄=中国最大IT O2O社区。
-
-
- DBLE
-
DBLE是爱可生基于MySQL的高可扩展性的分布式中间件,重点提升功能和性能优化,支持复杂查询,增强了如分布式事务,SQL支持度等核心功能,DBLE正适用于高并发及TB级海量数据处理场景。dble是基于开源项目MyCat的,其授权协议为GPL,采用java语言进行开发。
DBLE解决了哪些问题
- 数据水平拆分
当单个MySQL实例成为业务发展瓶颈,可使用DBLE来替换原始的MySQL实例,实现数据水平拆分;
- 与MySQL协议兼容
可以直接用它替换MySQL来为你的应用程序提供新的存储,而无需更改任何代码;
- SQL支持
支持SQL 92标准和MySQL方言。我们支持复杂的SQL查询,如group by,order by,distinct,join,union,sub-query等等。
- 查询优化
优化复杂查询,包括但不限于全局表连接分片表,ER关系表,子查询,简化选择项等。
- 分布式事务支持
使用两阶段提交协议实现了分布式事务,在确保系统性能的前提条件下,保证了分布式事务的数据一致性。
TiDB 是 PingCAP 公司受 Google Spanner / F1 论文启发而设计的开源分布式 HTAP (Hybrid Transactional and Analytical Processing) 数据库,结合了传统的 RDBMS 和 NoSQL 的最佳特性。
TiDB 兼容 MySQL,支持无限的水平扩展,具备强一致性和高可用性。TiDB 的目标是为 OLTP (Online Transactional Processing) 和 OLAP (Online Analytical Processing) 场景提供一站式的解决方案。
TiDB 是一个分布式 NewSQL 数据库。它支持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和 MySQL 协议,具有数据强一致的高可用特性,是一个不仅适合 OLTP 场景还适合 OLAP 场景的混合数据库。
- TiDB、TiKV、Placement Driver (PD) 的主要作用
TiDB 是 Server 计算层,主要负责 SQL 的解析、制定查询计划、生成执行器。
TiKV 是分布式 Key-Value 存储引擎,用来存储真正的数据,简而言之,TiKV 是 TiDB 的存储引擎。
PD 是 TiDB 集群的管理组件,负责存储 TiKV 的元数据,同时也负责分配时间戳以及对 TiKV 做负载均衡调度。
- TIDB的特点
- TiDB 使用起来很简单,可以将 TiDB 集群当成 MySQL 来用,你可以将 TiDB 用在任何以 MySQL 作为后台存储服务的应用中,并且基本上不需要修改应用代码,同时你可以用大部分流行的 MySQL 管理工具来管理 TiDB。
- TiDB 目前还不支持触发器、存储过程、自定义函数、外键,除此之外,TiDB 支持绝大部分 MySQL 5.7 的语法
- TiDB 天然具备高可用特性,TiDB、TiKV、PD 这三个组件都能容忍部分实例失效,不影响整个集群的可用性。
- TiDB 使用 Raft 在多个副本之间做数据同步,从而保证数据的强一致,单个副本失效时,不影响数据的可靠性。
- TiDB 支持 ACID 分布式事务,事务模型是以 Google 的 Percolator 模型为基础,并做了一些优化。这个模型需要一个时间戳分配器,分配唯一且递增的时间戳。在 TiDB 集群中,PD 承担时间戳分配器的角色。
- 只要支持 MySQL Client/Driver 的编程语言,都可以直接使用 TiDB。
TiDB 具备如下核心特性
- 高度兼容 MySQL
大多数情况下,无需修改代码即可从 MySQL 轻松迁移至 TiDB,分库分表后的 MySQL 集群亦可通过 TiDB 工具进行实时迁移。
- 水平弹性扩展
通过简单地增加新节点即可实现 TiDB 的水平扩展,按需扩展吞吐或存储,轻松应对高并发、海量数据场景。
- 分布式事务
TiDB 100% 支持标准的 ACID 事务。
- 真正金融级高可用
相比于传统主从 (M-S) 复制方案,基于 Raft 的多数派选举协议可以提供金融级的 100% 数据强一致性保证,且在不丢失大多数副本的前提下,可以实现故障的自动恢复 (auto-failover),无需人工介入。
- 一站式 HTAP 解决方案
TiDB 作为典型的 OLTP 行存数据库,同时兼具强大的 OLAP 性能,配合 TiSpark,可提供一站式 HTAP 解决方案,一份存储同时处理 OLTP & OLAP,无需传统繁琐的 ETL 过程。
- 云原生 SQL 数据库
TiDB 是为云而设计的数据库,同 Kubernetes 深度耦合,支持公有云、私有云和混合云,使部署、配置和维护变得十分简单。
TiDB 的设计目标是 100% 的 OLTP 场景和 80% 的 OLAP 场景,更复杂的 OLAP 分析可以通过 TiSpark 项目来完成。
TiDB 对业务没有任何侵入性,能优雅的替换传统的数据库中间件、数据库分库分表等Sharding方案。同时它也让开发运维人员不用关注数据库 Scale 的细节问题,专注于业务开发,极大的提升研发的生产力。
- 相关技术介绍
- Raft
Raft是一种一致性协议,能提供强一致的数据复制保证,TiDB最底层用 Raft来同步数据。每次写入都要写入多数副本,才能对外返回成功,这样即使丢掉少数副本,也能保证系统中还有最新的数据。比如最大 3 副本的话,每次写入 2 副本才算成功,任何时候,只丢失一个副本的情况下,存活的两个副本中至少有一个具有最新的数据。
相比 Master-Slave 方式的同步,同样是保存三副本,Raft的方式更为高效,写入的延迟取决于最快的两个副本,而不是最慢的那个副本。所以使用 Raft 同步的情况下,异地多活成为可能。
在典型的两地三中心场景下,每次写入只需要本数据中心以及离得近的一个数据中心写入成功就能保证数据的一致性,而并不需要三个数据中心都写成功。但是这并不意味着在任何场景都能构建跨机房部署的业务,当写入量比较大时候,机房之间的带宽和延迟成为关键因素,如果写入速度超过机房之间的带宽,或者是机房之间延迟过大,整个 Raft 同步机制依然无法很好的运转。
-
- 分布式事务
TiDB 提供完整的分布式事务,事务模型是在Google Percolator的基础上做了一些优化。这里介绍两点:
乐观锁
TiDB 的事务模型采用乐观锁,只有在真正提交的时候,才会做冲突检测,如果有冲突,则需要重试。这种模型在冲突严重的场景下,会比较低效,因为重试之前的操作都是无效的,需要重复做。
举一个比较极端的例子,就是把数据库当做计数器用,如果访问的并发度比较高,那么一定会有严重的冲突,导致大量的重试甚至是超时。但是如果访问冲突并不十分严重,那么乐观锁模型具备较高的效率。所以在冲突严重的场景下,推荐在系统架构层面解决问题,比如将计数器放在 Redis 中。
事务大小限制
由于分布式事务要做两阶段提交,并且底层还需要做 Raft 复制,如果一个事务非常大,会使得提交过程非常慢,并且会卡住下面的 Raft 复制流程。为了避免系统出现被卡住的情况,我们对事务的大小做了限制:
- 单条 KV entry 不超过 6MB
- KV entry 的总条数不超过 30w
- KV entry 的总大小不超过 100MB
- 数据分片
TiKV 自动将底层数据按照 Key 的 Range 进行分片。每个 Region 是一个 Key的范围,从 StartKey到EndKey的左闭右开区间。Region 中的 Key-Value 总量超过一定值,就会自动分裂。
-
- SQL on KV
TiDB 自动将 SQL 结构映射为 KV 结构。简单来说,TiDB 做了两件事:1、一行数据映射为一个 KV,Key 以 TableID 构造前缀,以行 ID 为后缀;2、一条索引映射为一个 KV,Key 以 TableID+IndexID 构造前缀,以索引值构造后缀。
可以看到,对于一个表中的数据或者索引,会具有相同的前缀,这样在 TiKV 的 Key空间内,这些 Key-Value 会在相邻的位置。那么当写入量很大,并且集中在一个表上面时,就会造成写入的热点,特别是连续写入的数据中某些索引值也是连续的(比如 update time 这种按时间递增的字段),会再很少的几个 Region 上形成写入热点,成为整个系统的瓶颈。
同样,如果所有的数据读取操作也都集中在很小的一个范围内 (比如在连续的几万或者十几万行数据上),那么可能造成数据的访问热点。
-
- Secondary Index
TiDB 支持完整的二级索引,并且是全局索引,很多查询可以通过索引来优化。如果利用好二级索引,对业务非常重要,很多 MySQL 上的经验在 TiDB 这里依然适用,不过 TiDB 还有一些自己的特点,需要注意,这一节主要讨论在 TiDB 上使用二级索引的一些注意事项。
- 二级索引是否越多越好
二级索引能加速查询,但是要注意新增一个索引是有副作用的,在上一节中我们介绍了索引的存储模型,那么每增加一个索引,在插入一条数据的时候,就要新增一个 Key-Value,所以索引越多,写入越慢,并且空间占用越大。另外过多的索引也会影响优化器运行时间,并且不合适的索引会误导优化器。所以索引并不是越多越好。
- 对哪些列建索引比较合适
索引很重要但不是越多越好,我们需要根据具体的业务特点创建合适的索引。原则上我们需要对查询中需要用到的列创建索引,目的是提高性能。下面几种情况适合创建索引:
区分度比较大的列,通过索引能显著地减少过滤后的行数
有多个查询条件时,可以选择组合索引,注意需要把等值条件的列放在组合索引的前面。
- 通过索引查询和直接扫描 Table 的区别
TiDB 实现了全局索引,所以索引和Table中的数据并不一定在一个数据分片上,通过索引查询的时候,需要先扫描索引,得到对应的行 ID,然后通过行 ID 去取数据,所以可能会涉及到两次网络请求,会有一定的性能开销。
如果查询涉及到大量的行,那么扫描索引是并发进行,只要第一批结果已经返回,就可以开始去取 Table 的数据,所以这里是一个并行 + Pipeline 的模式,虽然有两次访问的开销,但是延迟并不会很大。
- 通过索引保证结果顺序
索引除了可以用来过滤数据之外,还能用来对数据排序,首先按照索引的顺序获取行 ID,然后再按照行 ID 的返回顺序返回行的内容,这样可以保证返回结果按照索引列有序。前面提到了扫索引和获取 Row 之间是并行 + Pipeline 模式,如果要求按照索引的顺序返回 Row,那么这两次查询之间的并发度设置的太高并不会降低延迟,所以默认的并发度比较保守。可以通过 tidb_index_serial_scan_concurrency 变量进行并发度调整。
第三章 TIDB原理
-
- 架构设计
TiDB 集群主要分为三个组件:
- 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 的一大特点,这里说的水平扩展包括两方面:计算能力和存储能力。TiDB Server 负责处理 SQL 请求,随着业务的增长,可以简单的添加 TiDB Server 节点,提高整体的处理能力,提供更高的吞吐。TiKV 负责存储数据,随着数据量的增长,可以部署更多的 TiKV Server 节点解决数据 Scale 的问题。PD 会在 TiKV 节点之间以 Region 为单位做调度,将部分数据迁移到新加的节点上。所以在业务的早期,可以只部署少量的服务实例(推荐至少部署 3 个 TiKV, 3 个 PD,2 个 TiDB),随着业务量的增长,按照需求添加 TiKV 或者 TiDB 实例。
- 高可用
高可用是 TiDB 的另一大特点,TiDB/TiKV/PD 这三个组件都能容忍部分实例失效,不影响整个集群的可用性。下面分别说明这三个组件的可用性、单个实例失效后的后果以及如何恢复。
- TiDB
TiDB 是无状态的,推荐至少部署两个实例,前端通过负载均衡组件对外提供服务。当单个实例失效时,会影响正在这个实例上进行的 Session,从应用的角度看,会出现单次请求失败的情况,重新连接后即可继续获得服务。单个实例失效后,可以重启这个实例或者部署一个新的实例。
- PD
PD 是一个集群,通过 Raft 协议保持数据的一致性,单个实例失效时,如果这个实例不是 Raft 的 leader,那么服务完全不受影响;如果这个实例是 Raft 的 leader,会重新选出新的 Raft leader,自动恢复服务。PD 在选举的过程中无法对外提供服务,这个时间大约是3秒钟。推荐至少部署三个 PD 实例,单个实例失效后,重启这个实例或者添加新的实例。
- TiKV
TiKV 是一个集群,通过 Raft 协议保持数据的一致性(副本数量可配置,默认保存三副本),并通过 PD 做负载均衡调度。单个节点失效时,会影响这个节点上存储的所有 Region。对于 Region 中的 Leader 节点,会中断服务,等待重新选举;对于 Region 中的 Follower 节点,不会影响服务。当某个 TiKV 节点失效,并且在一段时间内(默认 30 分钟)无法恢复,PD 会将其上的数据迁移到其他的 TiKV 节点上。
第四章 使用 Docker Compose 快速构建集群
-
- 项目介绍
本文档介绍如何在单机上通过 Docker Compose 快速一键部署一套 TiDB 测试集群。
Docker Compose 可以通过一个 YAML 文件定义多个容器的应用服务,然后一键启动或停止。
- 准备环境
- 确保你的机器上已安装:
- Docker(17.06.0 及以上版本)
- Docker Compose
- Git
- 快速部署
- 下载
tidb-docker-compose
git clone https://github.com/pingcap/tidb-docker-compose.git
- 创建并启动集群
cd tidb-docker-compose && docker-compose pull # Get the latest Docker images
docker-compose up -d
- 访问集群
mysql -h 127.0.0.1 -P 4000 -u root
访问集群 Grafana 监控页面:http://localhost:3000 默认用户名和密码均为 admin。
PID展示:
名称 | 描述 |
Storage Capacity | TiDB 集群总可用数据库空间大小 |
Current Storage Size | TiDB 集群目前已用数据库空间大小 |
Store Status -- up store | TiKV 正常节点数量 |
Store Status -- down store | TiKV 异常节点数量,如果大于 0,证明有节点不正常 |
Store Status -- offline store | 手动执行下线操作 TiKV 节点数量 |
Store Status -- Tombstone store | 下线成功的 TiKV 节点数量 |
Current storage usage | TiKV 集群存储空间占用率,超过 80% 应考虑添加 TiKV 节点 |
99%completed_cmds_duration_seconds | 99% pd-server 请求完成时间小于5ms |
Average completed_cmds_duration_seconds | pd-server 请求平均完成时间小于 50ms |
leader balance ratio | leader ratio 最大的节点与最小的节点的差,均衡状况下一般小于 5%,节点重启时会比较大 |
region balance ratio | region ratio 最大的节点与最小的节点的差,均衡状况下一般小于 5%,新增/下线节点时会比较大 |
|
|
TIKV展示:
名称 | 描述 |
handle_requests_duration_seconds | 请求 PD 获取 TSO 响应时间,小于 100ms
|
tidb server QPS | 集群的请求量 |
connection count | 从业务服务器连接到数据库的连接数和业务相关。但是如果连接数发生跳变,需要查明原因。比如突然掉为 0,可以检查网络是否中断; 如果突然上涨,需要检查业务。 |
statement count | 单位时间内不同类型语句执行的数目 |
Query Duration 99th percentile | 99% 的 query 时间 |
|
|
TIKV展示:
名称 | 描述 |
99% & 99.99% scheduler command duration | 99% & 99.99% 命令执行的时间 99% 小于 50ms;99.99% 小于 100ms |
95% & 99% storage async_request duration | 95% & 99% Raft 命令执行时间 95% 小于 50ms;99% 小于 100ms |
server report failure message | 发送失败或者收到了错误的 message 如果出现了大量的 unreachadble 的消息,表明系统网络出现了问题。如果有 store not match 这样的错误, 表明收到了不属于这个集群发过来的消息 |
Vote | Raft vote 的频率,通常这个值只会在发生 split 的时候有变动,如果长时间出现了 vote 偏高的情况,证明系统出现了严重的问题, 有一些节点无法工作了 |
95% & 99% coprocessor request duration | 95% & 99% coprocessor 执行时间 和业务相关,但通常不会出现持续高位的值 |
Pending task | 累积的任务数量,除了 pd worker,其他任何偏高都属于异常 |
stall | RocksDB Stall 时间大于 0,表明 RocksDB 忙不过来,需要注意 IO 和 CPU 了 |
channel full | channel 满了,表明线程太忙无法处理 如果大于 0,表明线程已经没法处理了 |
95% send_message_duration_seconds | 95% 发送消息的时间小于 50ms |
leader/region | 每个 TiKV 的 leader/region 数量 |
|
|
|
|
集群数据可视化展示: