1. TiDB介绍
TiDB 是分布式关系型数据库,是一款同时支持在线事务处理与在线分析处理的融合型分布式数据库产品,具备水平扩容或者缩容、金融级高可用、云原生的分布式数据库、兼容 MySQL 5.7 协议和 MySQL 生态等重要特性。目标是为用户提供一站式 OLTP (Online Transactional Processing)、OLAP (Online Analytical Processing)。TiDB 适合高可用、强一致要求较高、数据规模较大等各种应用场景。TiBD也是NewSQL的一种。
OLTP:联机的事务处理,特点是在短时间内返回查询结果,对应的是关系型数据库,例如mysql,sqlserver,oracle等,底层使用的innodb引擎,B+ 树等数据结构。
OLAP:联机的分析处理,特点是对历史数据分析,然后产生决策性的影响(大数据分析),对应的是数据库,例如HIVE(数据仓库),Hbase。
关系型数据库(SQL):
缺点:
- 不支持在线的数据库扩容,缩容。
- 大量数据查询非常慢
- 并发能力差(使用集群,分库,分表,mycat 实现但是成本较大)
优点:
- 关系型数据库
非关系型数据库(NOSQL):
缺点:
- 致命缺点丢失数据
- 不能联查
优点:
- 性能高
- 并发能力强
- 支持在线的数据库扩容,缩容
NewSQL:结合了关系型和非关系型数据库的优势可以做到以下
- 并发能力高
- 支持在线的数据库扩容,缩容
- 支持云原生
- 可以联查
2. 架构解析
- TiDB Server:SQL 层,对外暴露 MySQL 协议的连接 endpoint,负责接受客户端的连接,执行 SQL 解析和优化,最终生成分布式执行计划。TiDB 层本身是无状态的,实践中可以启动多个 TiDB 实例,通过负载均衡组件(如 LVS、HAProxy 或 F5)对外提供统一的接入地址,客户端的连接可以均匀地分摊在多个 TiDB 实例上以达到负载均衡的效果。TiDB Server 本身并不存储数据,只是解析 SQL,将实际的数据读取请求转发给底层的存储节点 TiKV(或 TiFlash)。
- PD (Placement Driver) Server:整个 TiDB 集群的元信息管理模块,负责存储每个 TiKV 节点实时的数据分布情况和集群的整体拓扑结构,提供 TiDB Dashboard 管控界面,并为分布式事务分配事务 ID。PD 不仅存储元信息,同时还会根据 TiKV 节点实时上报的数据分布状态,下发数据调度命令给具体的 TiKV 节点,可以说是整个集群的“大脑”。此外,PD 本身也是由至少 3 个节点构成,拥有高可用的能力。建议部署奇数个 PD 节点。
- 存储节点
- TiKV Server:负责存储数据,从外部看 TiKV 是一个分布式的提供事务的 Key-Value 存储引擎。存储数据的基本单位是 Region,每个 Region 负责存储一个 Key Range(从 StartKey 到 EndKey 的左闭右开区间)的数据,每个 TiKV 节点会负责多个 Region。TiKV 的 API 在 KV 键值对层面提供对分布式事务的原生支持,默认提供了 SI (Snapshot Isolation) 的隔离级别,这也是 TiDB 在 SQL 层面支持分布式事务的核心。TiDB 的 SQL 层做完 SQL 解析后,会将 SQL 的执行计划转换为对 TiKV API 的实际调用。所以,数据都存储在 TiKV 中。另外,TiKV 中的数据都会自动维护多副本(默认为三副本),天然支持高可用和自动故障转移。
- TiFlash:TiFlash 是一类特殊的存储节点。和普通 TiKV 节点不一样的是,在 TiFlash 内部,数据是以列式的形式进行存储,主要的功能是为分析型的场景加速。
TiDB的搭建
-
操作系统
-
搭建条件
TiDB 支持部署和运行在 Intel x86-64 架构的 64 位通用硬件服务器平台或者 ARM 架构的硬件服务器平台。对于开发,测试,及生产环境的服务器硬件配置(不包含操作系统 OS 本身的占用)有以下要求和建议:
- 下载文件
#克隆安装脚本,或者直接复制下载好的文件内容(下载所有的脚本到,然后把整个复制到指定的目录下)
git clone https://github.com/pingcap/tidb-docker-compose.git
#执行docker-compose之前先需要清除本机挂载,如果之前安装过
docker volume rm $(docker volume ls -q)
#安装
docker-compose up -d
#设置密码
set password for 'root'@'%' = '123456';
搭建成功可用mysql工具软件连接测试,以后就可以如同mysql一样使用了。
同时可以使用http:IP:3000 查看数据库的状态
4. 数据的一致性
1. 选举
节点是可以自己给自己投票的,启动的时候获得了大多数的票的就会作为leader,当出现投票一致的时候,就会进行重新的选举。
2. 日志复制
从客户端来的数据,先是主节点收到数据,主节点把数据通过raft协议把日志发送到所有的从节点。当超过半数(包括半数)的从节点返回ack 后,主节点认为数据保存落盘 。然后,继续做1.返回给客户端ack 数据收到,当返回客户端成功后,主节点然后通知从节点,把上次的数据改为提交状态(提交状态的数据,才能被查询到)。至于没有给主节点返回ack的从节点,主节点会重复给这些从节点日志复制。
如果,主机点和其他的从节点网络断开,则客户端会写入数据失败,其他的从节点会从新的选举主节点,保证后面的数据能写入成功。经过一段时间旧的主节点从新连接上来后,旧 的主节点会对写入失败的数据做回滚,然后作为新的主节点的从节点,同步新的主节点的数据。
注意:当网络不是很好的时候,已经产生了新的主节点。新的客户端对旧的数据做修改操作后。会造成旧的客户端连接旧的主节点对查出来的数据是旧的。
5. 对接Spark引擎大数据查询
1. Spark介绍
Apache Spark是专为大规模数据处理而设计的快速通用的计算引擎 。现在形成一个高速发展应用广泛的生态系统。
Spark 主要有三个特点 :
首先,高级 API 剥离了对集群本身的关注,Spark 应用开发者可以专注于应用所要做的计算本身。
其次,Spark 很快,支持交互式计算和复杂算法。
最后,Spark 是一个通用引擎,可用它来完成各种各样的运算,包括 SQL 查询、文本处理、机器学习等,而在 Spark 出现之前,我们一般需要学习各种各样的引擎来分别处理这些需求。
- 更快的速度
内存计算下,Spark 比 Hadoop 快100倍。
- 易用性
Spark 提供了80多个高级运算符。
- 通用性
Spark 提供了大量的库,包括Spark Core、Spark SQL、Spark Streaming、MLlib、GraphX。 开发者可以在同一个应用程序中无缝组合使用这些库。
- 支持多种资源管理器
Spark 支持 Hadoop YARN,Apache Mesos,及其自带的独立集群管理器
- Spark生态系统
- Shark:Shark基本上就是在Spark的框架基础上提供和Hive一样的HiveQL命令接口,为了最大程度的保持和Hive的兼容性,Spark使用了Hive的API来实现query Parsing和 Logic Plan generation,最后的PhysicalPlan execution阶段用Spark代替HadoopMapReduce。通过配置Shark参数,Shark可以自动在内存中缓存特定的RDD,实现数据重用,进而加快特定数据集的检索。同时,Shark通过UDF用户自定义函数实现特定的数据分析学习算法,使得SQL数据查询和运算分析能结合在一起,最大化RDD的重复使用。
- SparkR:SparkR是一个为R提供了轻量级的Spark前端的R包。 SparkR提供了一个分布式的data frame数据结构,解决了 R中的data frame只能在单机中使用的瓶颈,它和R中的data frame 一样支持许多操作,比如select,filter,aggregate等等。(类似dplyr包中的功能)这很好的解决了R的大数据级瓶颈问题。 SparkR也支持分布式的机器学习算法,比如使用MLib机器学习库。 [4] SparkR为Spark引入了R语言社区的活力,吸引了大量的数据科学家开始在Spark平台上直接开始数据分析之旅。
Hadoop:核心思想是分而治之。其中有三个组件:
- hdfs:分部署的储存
- mapduce:由map 和duce 组成。
- 容器,任务执行容器,方便垃圾回收,管理分配所有节点的资源,也是资源调度器。
以下是hadoop 下的一个节点的结构:
Hadoop和数据库结构就变成了以下状态:
hadoop 存在的问题就是性能低:主要原因就是原始数据通过map从新保存到磁盘中,做排序后reduce又从新的从硬盘读取从新放入磁盘。
所以现在开发出了spark在内存中对数据做汇总以提高它的性能:
以下是结构体
2. Spark的使用
docker exec -it tidb-docker-compose_tispark-master_1 /bin/bash
cd /opt/spark/data/tispark-sample-data
//插入测试数据
mysql --local-infile=1 -h IP -P 4000 -u root -p123456 < dss.ddl
插入数据成功:
可以通过mysql 数据库查看到数据数据库
使用shark查询数据:
cd /opt/spark/bin
#启动shell 窗口,会加载一些组件
./spark-shell
#导入组件
import org.apache.spark.sql.TiContext
#定义对象
var ti=new TiContext(spark)
#定义参数
ti.tidbMapDatabase("TPCH_001")
spark.sql("select count(*) from lineitem").show
spark.sql(
"""select
| l_returnflag,
| l_linestatus,
| sum(l_quantity) as sum_qty,
| sum(l_extendedprice) as sum_base_price,
| sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
| sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge,
| avg(l_quantity) as avg_qty,
| avg(l_extendedprice) as avg_price,
| avg(l_discount) as avg_disc,
| count(*) as count_order
|from
| lineitem
|where
| l_shipdate <= date '1998-12-01' - interval '90' day
|group by
| l_returnflag,
| l_linestatus
|order by
| l_returnflag,
| l_linestatus
""".stripMargin).show
以下是查询的结果:
注意:
- spark 现在存在的问题吃内存,
- 稳定性待测试
6. 处理大数据
为了提升数据的读写性能TiDB对硬盘做了分块,并且分配的磁盘是递增增加:如下图:
数据写入:当数据写入时,首先写入内存中,同时追加到日志中,当把分配的内存写满后,把数据转移到较小的磁盘中。然后删除日志文件,当较小的磁盘写满后转存到较大的磁盘中,以此类推
数据修改删除:删除的数据会记录版本号,处理还是按照日志追加,同理修改记录也会进入磁盘,LSM树TiDB的底层会做处理。
数据读取:开始先读取内存,如果内存没有就找较小的磁盘,较小的磁盘没有找较大的磁盘,以此类推。为了提升性能,减少对磁盘的查询,增加了布隆过滤器。