TiDB介绍

2023-11-05

目录

TiDB 简介

一、四大核心应用场景

二、TiDB 整体架构

三、TiDB 数据库的存储 

Key-Value Pairs(键值对)

本地存储 (RocksDB)

Raft 协议

Region

MVCC

分布式 ACID 事务

参考


TiDB 简介

TiDB 是 PingCAP 公司自主设计、研发的开源分布式关系型数据库,是一款同时支持在线事务处理与在线分析处理 (Hybrid Transactional and Analytical Processing, HTAP) 的融合型分布式数据库产品,具备水平扩容或者缩容、金融级高可用、实时 HTAP、云原生的分布式数据库、兼容 MySQL 5.7 协议和 MySQL 生态等重要特性。目标是为用户提供一站式 OLTP (Online Transactional Processing)、OLAP (Online Analytical Processing)、HTAP 解决方案。TiDB 适合高可用、强一致要求较高、数据规模较大等各种应用场景。


一、四大核心应用场景

  • 对数据一致性及高可靠、系统高可用、可扩展性、容灾要求较高的金融行业属性的场景

    众所周知,金融行业对数据一致性及高可靠、系统高可用、可扩展性、容灾要求较高。传统的解决方案是同城两个机房提供服务、异地一个机房提供数据容灾能力但不提供服务,此解决方案存在以下缺点:资源利用率低、维护成本高、RTO (Recovery Time Objective) 及 RPO (Recovery Point Objective) 无法真实达到企业所期望的值。TiDB 采用多副本 + Multi-Raft 协议的方式将数据调度到不同的机房、机架、机器,当部分机器出现故障时系统可自动进行切换,确保系统的 RTO <= 30s 及 RPO = 0。

  • 对存储容量、可扩展性、并发要求较高的海量数据及高并发的 OLTP 场景

    随着业务的高速发展,数据呈现爆炸性的增长,传统的单机数据库无法满足因数据爆炸性的增长对数据库的容量要求,可行方案是采用分库分表的中间件产品或者 NewSQL 数据库替代、采用高端的存储设备等,其中性价比最大的是 NewSQL 数据库,例如:TiDB。TiDB 采用计算、存储分离的架构,可对计算、存储分别进行扩容和缩容,计算最大支持 512 节点,每个节点最大支持 1000 并发,集群容量最大支持 PB 级别。

  • Real-time HTAP 场景

    随着 5G、物联网、人工智能的高速发展,企业所生产的数据会越来越多,其规模可能达到数百 TB 甚至 PB 级别,传统的解决方案是通过 OLTP 型数据库处理在线联机交易业务,通过 ETL 工具将数据同步到 OLAP 型数据库进行数据分析,这种处理方案存在存储成本高、实时性差等多方面的问题。TiDB 在 4.0 版本中引入列存储引擎 TiFlash 结合行存储引擎 TiKV 构建真正的 HTAP 数据库,在增加少量存储成本的情况下,可以在同一个系统中做联机交易处理、实时数据分析,极大地节省企业的成本。

  • 数据汇聚、二次加工处理的场景

    当前绝大部分企业的业务数据都分散在不同的系统中,没有一个统一的汇总,随着业务的发展,企业的决策层需要了解整个公司的业务状况以便及时做出决策,故需要将分散在各个系统的数据汇聚在同一个系统并进行二次加工处理生成 T+0 或 T+1 的报表。传统常见的解决方案是采用 ETL + Hadoop 来完成,但 Hadoop 体系太复杂,运维、存储成本太高无法满足用户的需求。与 Hadoop 相比,TiDB 就简单得多,业务通过 ETL 工具或者 TiDB 的同步工具将数据同步到 TiDB,在 TiDB 中可通过 SQL 直接生成报表。

二、TiDB 整体架构

与传统的单机数据库相比,TiDB 具有以下优势:

  • 纯分布式架构,拥有良好的扩展性,支持弹性的扩缩容
  • 支持 SQL,对外暴露 MySQL 的网络协议,并兼容大多数 MySQL 的语法,在大多数场景下可以直接替换 MySQL
  • 默认支持高可用,在少数副本失效的情况下,数据库本身能够自动进行数据修复和故障转移,对业务透明
  • 支持 ACID 事务,对于一些有强一致需求的场景友好,例如:银行转账
  • 具有丰富的工具链生态,覆盖数据迁移、同步、备份等多种场景

在内核设计上,TiDB 分布式数据库将整体架构拆分成了多个模块,各模块之间互相通信,组成完整的 TiDB 系统。对应的架构图如下:

architecture

  • 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 数据库的存储 

主要介绍 TiKV 的一些设计思想和关键概念。

storage-architecture

Key-Value Pairs(键值对)

作为保存数据的系统,首先要决定的是数据的存储模型,也就是数据以什么样的形式保存下来。TiKV 的选择是 Key-Value 模型,并且提供有序遍历方法。

TiKV 数据存储的两个关键点:

  1. 这是一个巨大的 Map(可以类比一下 C++ 的 std::map),也就是存储的是 Key-Value Pairs(键值对)
  2. 这个 Map 中的 Key-Value pair 按照 Key 的二进制顺序有序,也就是可以 Seek 到某一个 Key 的位置,然后不断地调用 Next 方法以递增的顺序获取比这个 Key 大的 Key-Value。

注意,本文所说的 TiKV 的 KV 存储模型和 SQL 中的 Table 无关。本文不讨论 SQL 中的任何概念,专注于讨论如何实现 TiKV 这样一个高性能、高可靠性、分布式的 Key-Value 存储。

本地存储 (RocksDB)

任何持久化的存储引擎,数据终归要保存在磁盘上,TiKV 也不例外。但是 TiKV 没有选择直接向磁盘上写数据,而是把数据保存在 RocksDB 中,具体的数据落地由 RocksDB 负责。这个选择的原因是开发一个单机存储引擎工作量很大,特别是要做一个高性能的单机引擎,需要做各种细致的优化,而 RocksDB 是由 Facebook 开源的一个非常优秀的单机 KV 存储引擎,可以满足 TiKV 对单机引擎的各种要求。这里可以简单的认为 RocksDB 是一个单机的持久化 Key-Value Map。

Raft 协议

接下来 TiKV 的实现面临一件更难的事情:如何保证单机失效的情况下,数据不丢失,不出错?

简单来说,需要想办法把数据复制到多台机器上,这样一台机器无法服务了,其他的机器上的副本还能提供服务;复杂来说,还需要这个数据复制方案是可靠和高效的,并且能处理副本失效的情况。TiKV 选择了 Raft 算法。Raft 是一个一致性协议,本文只会对 Raft 做一个简要的介绍,细节问题可以参考它的论文。Raft 提供几个重要的功能:

  • Leader(主副本)选举
  • 成员变更(如添加副本、删除副本、转移 Leader 等操作)
  • 日志复制

TiKV 利用 Raft 来做数据复制,每个数据变更都会落地为一条 Raft 日志,通过 Raft 的日志复制功能,将数据安全可靠地同步到复制组的每一个节点中。不过在实际写入中,根据 Raft 的协议,只需要同步复制到多数节点,即可安全地认为数据写入成功。

Raft in TiDB

总结一下,通过单机的 RocksDB,TiKV 可以将数据快速地存储在磁盘上;通过 Raft,将数据复制到多台机器上,以防单机失效。数据的写入是通过 Raft 这一层的接口写入,而不是直接写 RocksDB。通过实现 Raft,TiKV 变成了一个分布式的 Key-Value 存储,少数几台机器宕机也能通过原生的 Raft 协议自动把副本补全,可以做到对业务无感知。

Region

首先,为了便于理解,在此节,假设所有的数据都只有一个副本。前面提到,TiKV 可以看做是一个巨大的有序的 KV Map,那么为了实现存储的水平扩展,数据将被分散在多台机器上。对于一个 KV 系统,将数据分散在多台机器上有两种比较典型的方案:

  • Hash:按照 Key 做 Hash,根据 Hash 值选择对应的存储节点。
  • Range:按照 Key 分 Range,某一段连续的 Key 都保存在一个存储节点上。

TiKV 选择了第二种方式,将整个 Key-Value 空间分成很多段,每一段是一系列连续的 Key,将每一段叫做一个 Region,可以用 [StartKey,EndKey) 这样一个左闭右开区间来描述。每个 Region 中保存的数据量默认维持在 96 MiB 左右(可以通过配置修改)。

Region in TiDB

注意,这里的 Region 还是和 SQL 中的表没什么关系。 这里的讨论依然不涉及 SQL,只和 KV 有关。

将数据划分成 Region 后,TiKV 将会做两件重要的事情:

  • 以 Region 为单位,将数据分散在集群中所有的节点上,并且尽量保证每个节点上服务的 Region 数量差不多。
  • 以 Region 为单位做 Raft 的复制和成员管理。

这两点非常重要:

  • 先看第一点,数据按照 Key 切分成很多 Region,每个 Region 的数据只会保存在一个节点上面(暂不考虑多副本)。TiDB 系统会有一个组件 (PD) 来负责将 Region 尽可能均匀的散布在集群中所有的节点上,这样一方面实现了存储容量的水平扩展(增加新的节点后,会自动将其他节点上的 Region 调度过来),另一方面也实现了负载均衡(不会出现某个节点有很多数据,其他节点上没什么数据的情况)。同时为了保证上层客户端能够访问所需要的数据,系统中也会有一个组件 (PD) 记录 Region 在节点上面的分布情况,也就是通过任意一个 Key 就能查询到这个 Key 在哪个 Region 中,以及这个 Region 目前在哪个节点上(即 Key 的位置路由信息)。至于负责这两项重要工作的组件 (PD),会在后续介绍。
  • 对于第二点,TiKV 是以 Region 为单位做数据的复制,也就是一个 Region 的数据会保存多个副本,TiKV 将每一个副本叫做一个 Replica。Replica 之间是通过 Raft 来保持数据的一致,一个 Region 的多个 Replica 会保存在不同的节点上,构成一个 Raft Group。其中一个 Replica 会作为这个 Group 的 Leader,其他的 Replica 作为 Follower。默认情况下,所有的读和写都是通过 Leader 进行,读操作在 Leader 上即可完成,而写操作再由 Leader 复制给 Follower。

大家理解了 Region 之后,应该可以理解下面这张图:

TiDB Storage

以 Region 为单位做数据的分散和复制,TiKV 就成为了一个分布式的具备一定容灾能力的 KeyValue 系统,不用再担心数据存不下,或者是磁盘故障丢失数据的问题。

MVCC

很多数据库都会实现多版本并发控制 (MVCC),TiKV 也不例外。设想这样的场景:两个客户端同时去修改一个 Key 的 Value,如果没有数据的多版本控制,就需要对数据上锁,在分布式场景下,可能会带来性能以及死锁问题。TiKV 的 MVCC 实现是通过在 Key 后面添加版本号来实现,简单来说,没有 MVCC 之前,可以把 TiKV 看做这样的:

 

Key1 -> Value Key2 -> Value …… KeyN -> Value

有了 MVCC 之后,TiKV 的 Key 排列是这样的:

 

Key1_Version3 -> Value Key1_Version2 -> Value Key1_Version1 -> Value …… Key2_Version4 -> Value Key2_Version3 -> Value Key2_Version2 -> Value Key2_Version1 -> Value …… KeyN_Version2 -> Value KeyN_Version1 -> Value ……

注意,对于同一个 Key 的多个版本,版本号较大的会被放在前面,版本号小的会被放在后面(见 Key-Value 一节,Key 是有序的排列),这样当用户通过一个 Key + Version 来获取 Value 的时候,可以通过 Key 和 Version 构造出 MVCC 的 Key,也就是 Key_Version。然后可以直接通过 RocksDB 的 SeekPrefix(Key_Version) API,定位到第一个大于等于这个 Key_Version 的位置。

分布式 ACID 事务

TiKV 的事务采用的是 Google 在 BigTable 中使用的事务模型:Percolator,TiKV 根据这篇论文实现,并做了大量的优化。

参考

TiDB 数据库的存储 | PingCAP 文档中心

TiDB整体架构以及在Mac系统上快速安装部署TiDB_mac tidb下载_不一样的雅兰酱的博客-CSDN博客 HomebrewCN: Homebrew 国内安装脚本

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TiDB介绍 的相关文章

随机推荐

  • Golang版本管理之Goup

    本地管理go的不同版本管理 推荐使用 https github com owenthereal goup 安装 curl sSf https raw githubusercontent com owenthereal goup master
  • 2022国赛官方评审C题要点

    2022年C题评阅要点 本题通过对古代玻璃制品的化学成分数据分析 研究有无风化玻璃制品成分的变化规律 以及高钾 铅钡两种玻璃类型的化学成分统计规律 并探索亚分类的方法 进而可以依据未知分类的文物化学成分对文物进行准确的分类 本题数据的主要特
  • 怎么选酸奶

  • C# TCP/IP通讯协议的整理(二)附带——与欧姆龙PLC通讯

    进行了下优化 OmronParent中在new MyClient 时 设置端口号之前我是固定了 现在把它也开放出来 首先对MyClient类 进行一个小小的升级 添加发送和接收字节数组 using System using System C
  • [GXYCTF 2019]Ping Ping Ping

    禁了空格 并且不能用 IFS 因为 也禁了 ls发现 flag也被禁了 看index php的源码 cat IFS 9index php 可以base64编码绕过 echo ISF 9Y2F0IGZsYWcucGhw base64 IFS
  • AD16 如何锁定多根线 DDR3

    如何在altium designer中快速的锁定一整条信号线 如下图的DDR3走线 咱们随意选择一条 当你点击的时候 只能选中一部分 一 按下 Ctrl H 快捷键后 鼠标点击到要选中的线 你会发现 和这个线相关的线 过孔都被选中 如箭头所
  • 猴子爬山【Java】

    猴子爬山 Java 一天一只顽猴想去从山脚爬到山顶 途中经过一个有个N个台阶的阶梯 但是这猴子有一个习惯 每一次只能跳1步或跳3步 试问猴子通过这个阶梯有多少种不同的跳跃方式 输入描述 输入只有一个整数N 0
  • lora:low-rank adaption of large language models

    THUNLP 领读 ICLR 低秩微调大模型 LoRA OpenBMB论文速读 第3期 哔哩哔哩 bilibili 用脑图 十分钟 OpenBMB 论文速读 第3 期来了 本期领读人是清华大学自然语言处理实验室的本科生 带大家高效读完一篇关
  • 算法训练营第二十八天(8.11)

    目录 LeeCode 455 Assign Cookies LeeCode 376 Wiggle Subsequence LeeCode 53 Maximum Subarray LeeCode 455 Assign Cookies 题目地址
  • hbuilder webapp支付宝app支付

    前言 支付类的东西都是按照官方写的文档一步一步来就可以搞定 关键就是第一次弄 一脸懵 不成功就很烦躁 这次项目用的是hbuilder打包的app方式 框架用的是mui 其实app支付的重点就是在签名这块 官方有工具可以验签 一般签名不错的话
  • Java学习之抽象类&接口

    一 抽象类 1 抽象类的概述 一个没有方法体的方法应该定义为抽象方法 而类中如果有抽象方法 该类必须定义为抽象类 2 抽象类的特点 抽象类和抽象方法必须使用 abstract 关键字修饰 抽象类的定义 public abstract cla
  • 回归方法--一元回归,多元回归,逐步归回,Logistic 回归

    数学建模专栏 第三篇 MATLAB数据建模方法 上 常用方法 2017 07 21 卓金武 MATLAB 作 者 简 介 卓金武 MathWorks中国高级工程师 教育业务经理 在数据分析 数据挖掘 机器学习 数学建模 量化投资和优化等科学
  • Linux上如何查看某个进程的线程

    问题 我的程序在其内部创建并执行了多个线程 我怎样才能在该程序创建线程后监控其中单个线程 我想要看到带有它们名称的单个线程详细情况 如 CPU 内存使用率 线程是现代操作系统上进行并行执行的一个流行的编程方面的抽象概念 当一个程序内有多个线
  • JAVA中&&和两种符号

    可以用作逻辑与的运算符 表示逻辑与 and 当运算符两边的表达式的结果都为true时 整个运算结果才为true 否则 只要有一方为false 则结果为false 还具有短路的功能 即如果第一个表达式为false 则不再计算第二个表达式 例如
  • uni-app 微信小程序 onReachBottom 不生效

    问题描述 uni app 微信小程序 页面滑到底部 onReachBottom 没有生效 代码 pages json 配置 path style navigationBarTitleText 列表 onReachBottomDistance
  • 配置nginx服务器需要修改的配置文件为,01_Nginx安装,nginx下部署项目,nginx.conf配置文件修改,相关文件配置...

    1 下载Nginx 进入Nginx下载地址 http nginx org 2 下载pcre 这个是一个正则表达式的库 Nginx做rewriter的时候回用到这个库 进入pcre的官网 rewrite模式需要pcre http www pc
  • C语言的算法渐进分析

    C语言的基本结构 C语言由头文件组成 在C语言的源代码中有多个源文件 每一个源文件中包含了主函数 库函数以及自动以函数 源程序中可以有多个源文件 但是在运行的过程中只能有一个主函数 并且只能从主函数开始执行 C语言的格式为一行一句 在源程序
  • Android冷启动优化解析,flutter瀑布流列表

    TotalTime 242 WaitTime 288 Complete ThisTime 是指调用过程中最后一个Activity启动时间到这个Activity的 startActivityAndWait调用结束 TotalTime 是指调用
  • 云计算背后的秘密:NoSQL诞生的原因和优缺点

    聊聊为什么NoSQL会在关系型数据库已经非常普及的情况下异军突起 诞生的原因 随着互联网的不断发展 各种类型的应用层出不穷 所以导致在这个云计算的时代 对技术提出了更多的需求 主要体现在下面这四个方面 1 低延迟的读写速度 应用快速地反应能
  • TiDB介绍

    目录 TiDB 简介 一 四大核心应用场景 二 TiDB 整体架构 三 TiDB 数据库的存储 Key Value Pairs 键值对 本地存储 RocksDB Raft 协议 Region MVCC 分布式 ACID 事务 参考 TiDB