技术好文:TiDB架构及设计实现

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 技术好文: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 整体架构


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个节点。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为单位进行调度


三. 存储结构


一个 Region 的多个 Replica 会保存在不同的节点上,构成一个 Raft Group。其中一个 Replica 会作为这个 Group 的 Leader,其他的 Replica 作为 Follower。所有的读和写都是通过 Leader 进行,再由 Leader 复制给 Follower。


Key-Value 模型


TiDB对每个表分配一个TableID,每一个索引都会分配一个IndexID,每一行分配一个RowID(如果表有整形的Primary Key,那么会用Primary Key的值当做RowID),其中TableID在整个集群内唯一,IndexID/RowID 在表内唯一,这些ID都是int64类型。每行数据按照如下规则进行编码成Key-Value pair:


Key: tablePrefix_rowPrefix_tableID_rowID


Value: 【col1, col2, col3, col4】


其中Key的tablePrefix/rowPrefix都是特定的字符串常量,用于在KV空间内区分其他数据。对于Index数据,会按照如下规则编码成Key-Value pair


Key: tablePrefix_idxPrefix_tableID_indexID_indexColumnsValue


Value: rowID


Index 数据还需要考虑Unique Index 和 非 Unique Index两种情况,对于Unique Index,可以按照上述编码规则。但是对于非Unique Index,通常这种编码并不能构造出唯一的Key,因为同一个Index的tablePrefix_idxPrefix_tableIDindexID都一样,可能有多行数据的ColumnsValue都是一样的,所以对于非Unique Index的编码做了一点调整:


Key: tablePrefix_idxPrefix_tableID_indexID_ColumnsValue_rowID


Value:null


这样能够对索引中的每行数据构造出唯一的Key。注意上述编码规则中的Key里面的各种xxPrefix都是字符串常量,作用都是用来区分命名空间,以免不同类型的数据之间互相冲突,定义如下:


var(


tablePrefix = 【】byte{'t'}


recordPrefixSep = 【】byte("_r")


indexPrefixSep = 【】byte("_i")


//代码参考: https://weibo.com/u/7930355501

举个简单的例子,假设表中有3行数据:


1,“TiDB”, “SQL Layer”, 10


2,“TiKV”, “KV Engine”, 20


3,“PD”, “Manager”, 30


那么首先每行数据都会映射为一个Key-Value pair,注意,这个表有一个Int类型的Primary Key,所以RowID的值即为这个Primary Key的值。假设这个表的Table ID 为10,其中Row的数据为:


t_r_10_1 --> 【"TiDB", "SQL Layer", 10】


t_r_10_2 --> 【"TiKV", "KV Engine", 20】


t_r_10_3 --> 【"PD", "Manager", 30】


除了Primary Key之外,这个表还有一个Index,假设这个Index的ID为1,其数据为:


t_i_10_1_10_1 --> null


t_i_10_1_20_2 --> null


t_i_10_1_303 --> null


Database/Table 都有元信息,也就是其定义以及各项属性,这些信息也需要持久化,我们也将这些信息存储在TiKV中。每个Database/Table都被分配了一个唯一的ID,这个ID作为唯一标识,并且在编码为Key-Value时,这个ID都会编码到Key中,再加上m前缀。这样可以构造出一个Key,Value中存储的是序列化后的元数据。除此之外,还有一个专门的Key-Value存储当前Schema信息的版本。TiDB使用Google F1的Online Schema变更算法,有一个后台线程在不断的检查TiKV上面存储的Schema版本是否发生变化,并且保证在一定时间内一定能够获取版本的变化(如果确实发生了变化)。


四. SQL 运算


用户的 SQL 请求会直接或者通过 Load Balancer 发送到 tidb-server,tidb-server 会解析 MySQL Protocol Packet,获取请求内容,然后做语法解析、查询计划制定和优化、执行查询计划获取和处理数据。数据全部存储在 TiKV 集群中,所以在这个过程中 tidb-server 需要和 tikv-server 交互,获取数据。最后 tidb-server 需要将查询结果返回给用户。


五. 调 度


调度的流程


PD 不断的通过 Store 或者 Leader 的心跳包收集信息,获得整个集群的详细数据,并且根据这些信息以及调度策略生成调度操作序列,每次收到 Region Leader 发来的心跳包时,PD 都会检查是否有对这个 Region 待进行的操作,通过心跳包的回复消息,将需要进行的操作返回给 Region Leader,并在后面的心跳包中监测执行结果。


注意这里的操作只是给 Region Leader 的建议,并不保证一定能得到执行,具体是否会执行以及什么时候执行,由 Region Leader 自己根据当前自身状态来定。


信息收集


调度依赖于整个集群信息的收集,需要知道每个TiKV节点的状态以及每个Region的状态。TiKV集群会向PD汇报两类信息:


(1)每个TiKV节点会定期向PD汇报节点的整体信息。


TiKV节点(Store)与PD之间存在心跳包,一方面PD通过心跳包检测每个Store是否存活,以及是否有新加入的Store;另一方面,心跳包中也会携带这个Store的状态信息,主要包括:


a) 总磁盘容量


b) 可用磁盘容量


c) 承载的Region数量


d) 数据写入速度


e) 发送/接受的Snapshot数量(Replica之间可能会通过Snapshot同步数据)


f) 是否过载


g) 标签信息(标签是否具备层级关系的一系列Tag)


(2)每个 Raft Group 的 Leader 会定期向 PD 汇报Region信息


每个Raft Group 的 Leader 和 PD 之间存在心跳包,用于汇报这个Region的状态,主要包括下面几点信息:


a) Leader的位置


b) Followers的位置


c) 掉线Replica的个数


d) 数据写入/读取的速度


PD 不断的通过这两类心跳消息收集整个集群的信息,再以这些信息作为决策的依据。


除此之外,PD 还可以通过管理接口接受额外的信息,用来做更准确的决策。比如当某个 Store 的心跳包中断的时候,PD 并不能判断这个节点是临时失效还是永久失效,只能经过一段时间的等待(默认是 30 分钟),如果一直没有心跳包,就认为是 Store 已经下线,再决定需要将这个 Store 上面的 Region 都调度走。但是有的时候,是运维人员主动将某台机器下线,这个时候,可以通过 PD 的管理接口通知 PD 该 Store 不可用,PD 就可以马上判断需要将这个 Store 上面的 Region 都调度走。


调度策略


PD 收集以上信息后,还需要一些策略来制定具体的调度计划。


一个Region的Replica数量正确


当PD通过某个Region Leader的心跳包发现这个Region的Replica的数量不满足要求时,需要通过Add/Remove Replica操作调整Replica数量。出现这种情况的可能原因是:


A.某个节点掉线,上面的数据全部丢失,导致一些Region的Replica数量不足


B.某个掉线节点又恢复服务,自动接入集群,这样之前已经弥补了Replica的Region的Replica数量过多,需要删除某个Replica


C.管理员调整了副本策略,修改了max-replicas的配置


访问热点数量在 Store 之间均匀分配


每个Store以及Region Leader 在上报信息时携带了当前访问负载的信息,比如Key的读取/写入速度。PD会检测出访问热点,且将其在节点之间分散开。


各个 Store 的存储空间占用大致相等


每个 Store 启动的时候都会指定一个 Capacity 参数,表明这个 Store 的存储空间上限,PD 在做调度的时候,会考虑节点的存储空间剩余量。


控制调度速度,避免影响在线服务


调度操作需要耗费 CPU、内存、磁盘 IO 以及网络带宽,我们需要避免对线上服务造成太大影响。PD 会对当前正在进行的操作数量进行控制,默认的速度控制是比较保守的,如果希望加快调度(比如已经停服务升级,增加新节点,希望尽快调度),那么可以通过 pd-ctl 手动加快调度速度。


支持手动下线节点


当通过 pd-ctl 手动下线节点后,PD 会在一定的速率控制下,将节点上的数据调度走。当调度完成后,就会将这个节点置为下线状态。


一个 Raft Group 中的多个 Replica 不在同一个位置

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
9天前
|
运维 Kubernetes Cloud Native
云原生技术:容器化与微服务架构的完美结合
【10月更文挑战第37天】在数字化转型的浪潮中,云原生技术以其灵活性和高效性成为企业的新宠。本文将深入探讨云原生的核心概念,包括容器化技术和微服务架构,以及它们如何共同推动现代应用的发展。我们将通过实际代码示例,展示如何在Kubernetes集群上部署一个简单的微服务,揭示云原生技术的强大能力和未来潜力。
|
7天前
|
存储 分布式计算 关系型数据库
架构/技术框架调研
本文介绍了微服务间事务处理、调用、大数据处理、分库分表、大文本存储及数据缓存的最优解决方案。重点讨论了Seata、Dubbo、Hadoop生态系统、MyCat、ShardingSphere、对象存储服务和Redis等技术,提供了详细的原理、应用场景和优缺点分析。
|
9天前
|
监控 API 微服务
后端技术演进:从单体架构到微服务的转变
随着互联网应用的快速增长和用户需求的不断演化,传统单体架构已难以满足现代软件开发的需求。本文深入探讨了后端技术在面对复杂系统挑战时的演进路径,重点分析了从单体架构向微服务架构转变的过程、原因及优势。通过对比分析,揭示了微服务架构如何提高系统的可扩展性、灵活性和维护效率,同时指出了实施微服务时面临的挑战和最佳实践。
29 7
|
7天前
|
传感器 算法 物联网
智能停车解决方案之停车场室内导航系统(二):核心技术与系统架构构建
随着城市化进程的加速,停车难问题日益凸显。本文深入剖析智能停车系统的关键技术,包括停车场电子地图编辑绘制、物联网与传感器技术、大数据与云计算的应用、定位技术及车辆导航路径规划,为读者提供全面的技术解决方案。系统架构分为应用层、业务层、数据层和运行环境,涵盖停车场室内导航、车位占用检测、动态更新、精准导航和路径规划等方面。
38 4
|
8天前
|
Kubernetes Cloud Native 持续交付
云原生技术在现代应用架构中的实践与思考
【10月更文挑战第38天】随着云计算的不断成熟和演进,云原生(Cloud-Native)已成为推动企业数字化转型的重要力量。本文从云原生的基本概念出发,深入探讨了其在现代应用架构中的实际应用,并结合代码示例,展示了云原生技术如何优化资源管理、提升系统弹性和加速开发流程。通过分析云原生的优势与面临的挑战,本文旨在为读者提供一份云原生转型的指南和启示。
24 3
|
10天前
|
网络协议 数据挖掘 5G
适用于金融和交易应用的低延迟网络:技术、架构与应用
适用于金融和交易应用的低延迟网络:技术、架构与应用
39 5
|
8天前
|
运维 Kubernetes Cloud Native
云原生技术在现代应用架构中的实践与挑战####
本文深入探讨了云原生技术的核心概念、关键技术组件及其在实际项目中的应用案例,分析了企业在向云原生转型过程中面临的主要挑战及应对策略。不同于传统摘要的概述性质,本摘要强调通过具体实例揭示云原生技术如何促进应用的灵活性、可扩展性和高效运维,同时指出实践中需注意的技术债务、安全合规等问题,为读者提供一幅云原生技术实践的全景视图。 ####
|
12天前
|
Kubernetes Cloud Native 云计算
云原生技术深度解析:重塑企业IT架构的未来####
本文深入探讨了云原生技术的核心理念、关键技术组件及其对企业IT架构转型的深远影响。通过剖析Kubernetes、微服务、容器化等核心技术,本文揭示了云原生如何提升应用的灵活性、可扩展性和可维护性,助力企业在数字化转型中保持领先地位。 ####
|
14天前
|
存储 分布式计算 分布式数据库
风险数据集市整体架构及技术实现
【11月更文挑战第11天】在当今大数据时代,风险数据集市作为金融机构的核心基础设施之一,扮演着至关重要的角色。它不仅为银行、保险等金融机构提供了全面、准确的风险数据支持,还帮助这些机构实现了风险管理的精细化和智能化。本文将深入探讨一种基于大数据Lambda架构设计的风险数据集市整体架构,并详细介绍其底层实现原理及实现方式。
37 3
|
17天前
|
机器学习/深度学习 人工智能 自然语言处理
医疗行业的语音识别技术解析:AI多模态能力平台的应用与架构
AI多模态能力平台通过语音识别技术,实现实时转录医患对话,自动生成结构化数据,提高医疗效率。平台具备强大的环境降噪、语音分离及自然语言处理能力,支持与医院系统无缝集成,广泛应用于门诊记录、多学科会诊和急诊场景,显著提升工作效率和数据准确性。