8.1.2 TiDB存储引擎的原理

TiDB 简介

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

TiDB用来解决mysql单节点容量问题,有了TiDB之后,以往的技术如用redis缓存MySQL的数据的这种方案就没有必要存在了,MySQL的分布分表,各种复杂的不同的水平分表分库、垂直分表分库也没有必要去学了。TiDB都可以解决这些问题,因为它是一种分布式的。

分布式系统

分布式系统是一种其组件位于不同的联网计算机上的系统,然 后通过互相传递消息来进行通讯和协调,为了达到共同的目 标,这些组件会相互作用;换句话说,分布式系统把需要进行 大量计算的工程数据分割成若干个小块,由多台计算机分别进 行计算和存储,然后将结果统一合并到数据结论的科学;本质 上就是进行数据存储与计算的分治

带来的问题:CAP理论:一致性、可用性(主数据库宕机,从数据库进行替换使用)、分区容错性(分布式系统在遇到某节点或网络分区故障的时候仍然能够对外 提供满足一致性或可用性的服务;)

应用场景

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

TiDB 采用多副本 + Multi-Raft 协议的方式将数据调度到不同的机房、机架、机器,当部分机器出现故障时系统可自动进行切换,确保系统的 RTO <= 30s 及 RPO = 0。

RTO(Recovery Time Objective):恢复时间目标,即在发生系统故障或灾难事件时,恢复系统功能所需的时间。它代表了组织能够接受的最长系统停机时间。

RPO(Recovery Point Objective):恢复点目标,即在发生系统故障或灾难事件时,允许数据丢失的时间范围。它表示组织库接受的数据丢失程度。

RTO关注的是从故障中恢复正常操作所需的时间,而RPO关注的是在故障发生前可接受丢失的数据量。

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

TiDB 采用计算、存储分离的架构,可对计算、存储分别进行 扩容和缩容,计算最大支持 512 节点,每个节点最大支持 1000 并发,集群容量最大支持 PB 级别。

3、Real-time HTAP 场景

TiDB 在 4.0 版本中引入列存储引擎 TiFlash 结合行存储引擎 TiKV 构建真正的 HTAP 数据库,在增加少量存储成本的情况 下,可以在同一个系统中做联机交易处理、实时数据分析, 极大地节省企业的成本。

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

业务通过 ETL 工具或者 TiDB 的同步工具将数据同步到 TiDB,在 TiDB 中可通过 SQL 直接生成报表。(ETL 是将业务系统的数据经过抽取、清洗转换之后加载到数据仓库的过程,目的是将企业中的分散、零乱、标准不统一的数据整合到一起,为企业的决策提供分析依据)

关系型模型

在传统的在线交易场景里,关系型模型仍然是标准;关系型数 据库的关键在于一定要具备事务

事务

事务的本质是:并发控制的单元,是用户定义的一个操作序列;这些操作要么都做,要么都不做,是一个不可分割的工作单位;

为了保证系统始终处于一个完整且正确的状态;

ACID 特性

原子性:事务包含的全部操作时一个不可分割的整体;要么全部执 行,要么全部不执行;

一致性:事务的前后,所有的数据都保持一个一致的状态;不能违反 数据的一致性检测;

隔离性:各个并发事务之间互相影响的程度;主要规定多个并发事务 访问同一个数据资源,各个并发事务对该数据资源访问的行 为;不同的隔离性是应对不同的现象(脏读、可重复读、幻 读等);

持久性:事务一旦完成要将数据所做的变更记录下来;包括数据存储 和多副本的网络备份;

TiDB可以视为分布式的mysql

TiDB 部署本地测试集群

# 下载并安装 
TiUP curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
# 声明全局环境变量 
source .bash_profile 
# 运行最新版本的 TiDB 集群, 其中 TiDB、TiKV、PD 和 TiFlash 实例各 1 个
tiup playground 
# 如果想指定版本并运行多个
tiup playground v4.0.16 --db 3 --pd 3 --kv 3 -- monitor 
# 注意: 按照上面的部署, 在结束部署测试后 TiUP 会清理掉原 集群数据,重新执行该命令后会得到一个全新的集群。 # 如果希望持久化数据, 并指定存储目录为 /tmp/tidb 
tiup playground -T /tmp/tidb --host 0.0.0.0

与传统非分布式数据库架构对比

  • 两者都支持 ACID、事务强一致性;

  • 分布式架构,组件解耦,拥有良好的扩展性,支持弹性的扩缩容;

  • 默认支持高可用,在少数副本失效的情况下,数据库能够自动进 行故障转移,对业务透明;

  • 采用水平扩展,在大数据量、高吞吐的业务场景中具有先天优势;

  • 强项不在于轻量的简单 SQL 的响应速度,而在于大量高并发 SQL 的吞吐;

TiDB 分布式数据库整体架构

  • 由多模块组成,各模块互相通信,组成完整的 TiDB 系统;

  • 前端 stateless、后端 stateful (Raft);

  • 兼容 MySQL;

TiDB Server 的模块

SQL 层,对外暴露 MySQL 协议的连接 endpoint,负责接受客 户端的连接,执行 SQL 解析和优化,最终生成分布式执行计 划。TiDB 层本身是无状态的,实践中可以启动多个 TiDB 实例,通过负载均衡组件(如 LVS、HAProxy 或 F5)对外提供统 一的接入地址,客户端的连接可以均匀地分摊在多个 TiDB 实例 上以达到负载均衡的效果。TiDB Server 本身并不存储数据,只是解析SQL,将实际的数据读取请求转发给底层的存储节点 TiKV(或 TiFlash)。

数据映射关系

数据与 KV 的映射关系中定义如下:

tablePrefix     = []byte{'t'} 
recordPrefixSep = []byte{'r'} 
indexPrefixSep  = []byte{'i'} 

假设表结构如下:

CREATE TABLE User (   ID int,    Name varchar(20),    Role varchar(20),    Age int,    UID int,     PRIMARY KEY (ID),     KEY idxAge (Age),     UNIQUE KEY idxUID (UID) 
); 

假设表数据如下:

1, "TiDB", "SQL Layer", 10, 10001 
2, "TiKV", "KV Engine", 20, 10002 
3, "PD", "Manager", 30, 10003 

表数据与 KV 的映射关系

Key 的形式:tablePrefix{TableID}_recordPrefixSep{RowID}

Value 的形式:[col1, col2, col3, col4]

映射示例:

# 假设系统为user表分配了表ID为10
t10_r1 --> ["TiDB", "SQL Layer", 10, 10001] 
t10_r2 --> ["TiKV", "KV Engine", 20, 10002] 
t10_r3 --> ["PD",   "Manager",   30, 10003] 

索引数据和 KV 的映射关系

对于唯一索引:

Key 的形式: tablePrefix{tableID}_indexPrefixSep{indexID}_indexe dColumnsValue

Value 的形式: RowID

映射示例:

# 假设系统为idxUID 分配的索引ID为3
t10_i3_10001 --> 1 
t10_i3_10002 --> 2 
t10_i3_10003 --> 3 

非唯一索引:

Key 的形式: tablePrefix{TableID}_indexPrefixSep{IndexID}_indexe dColumnsValue_{RowID}

Value 的形式:null

映射示例:

# 假设系统为idxAge 分配的索引ID为2 
t10_i2_10_1 --> null 
t10_i2_20_2 --> null 
t10_i2_30_3 --> null 

PD(Placement Driver)Server

整个 TiDB 集群的元信息管理模块,负责存储每个 TiKV 节点实 时的数据分布情况和集群的整体拓扑结构,提供 TiDB Dashboard 管控界面,并为分布式事务分配事务 ID。PD 不仅 存储元信息,同时还会根据 TiKV 节点实时上报的数据分布状 态,下发数据调度命令给具体的 TiKV 节点,可以说是整个集群 的“大脑”。此外,PD 本身也是由至少 3 个节点构成,拥有高可 用的能力。建议部署奇数个 PD 节点。

调度需求

  1. 作为一个分布式高可用存储系统,必须满足的需求,包括几种:

  • 副本数量不能多也不能少

  • 副本需要根据拓扑结构分布在不同属性的机器上

  • 节点宕机或异常能够自动合理快速地进行容灾

  1. 作为一个良好的分布式系统,需要考虑的地方包括:

  • 维持整个集群的 Leader 分布均匀

  • 维持每个节点的储存容量均匀

  • 维持访问热点分布均匀

  • 控制负载均衡的速度,避免影响在线服务

  • 管理节点状态,包括手动上线/下线节点

满足第一类需求后,整个系统将具备强大的容灾功能。满足第 二类需求后,可以使得系统整体的资源利用率更高且合理,具 备良好的扩展性。

调度操作

  • 增加一个副本

  • 删除一个副本

  • 将 Leader 角色在一个 Raft Group 的不同副本之间 transfer (迁移)。

信息收集

  • 每个 TiKV 节点会定期向 PD 汇报节点的状态信息

  • 每个 Raft Group 的 Leader 会定期向 PD 汇报 Region 的状态信 息

存储节点

TiKV Server

负责存储数据,从外部看 TiKV 是一个分布式的提供事务的 KeyValue 存储引擎。存储数据的基本单位是 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 内部,数据是以列式的形式进行存储,主要的功 能是为分析型的场景加速。

  • 列式存储可以满足快速读取特定列的需求,在线分析处理往往需 要在上百列的宽表中读取指定列分析;

  • 列式存储就近存储同一列的数据,使用压缩算法可以得到更高的压缩率,减少存储占用的磁盘空间;

RocksDB

RocksDB 作为 TiKV 的核心存储引擎,用于存储 Raft 日志以及 用户数据。每个 TiKV 实例中有两个 RocksDB 实例,一个用于 存储 Raft 日志(通常被称为 raftdb),另一个用于存储用户数 据以及 MVCC 信息(通常被称为 kvdb)。kvdb 中有四个 ColumnFamily:raft、lock、default 和 write:

  • raft 列:用于存储各个 Region 的元信息。仅占极少量空间,用 户可以不必关注。

  • lock 列:用于存储悲观事务的悲观锁以及分布式事务的一阶段 Prewrite 锁。当用户的事务提交之后,lock cf 中对应的数据会 很快删除掉,因此大部分情况下 lock cf 中的数据也很少(少于 1GB)。如果 lock cf 中的数据大量增加,说明有大量事务等待提交,系统出现了 bug 或者故障。

  • write 列:用于存储用户真实的写入数据以及 MVCC 信息(该数 据所属事务的开始时间以及提交时间)。当用户写入了一行数据 时,如果该行数据长度小于 255 字节,那么会被存储 write 列 中,否则的话该行数据会被存入到 default 列中。由于 TiDB 的 非 unique 索引存储的 value 为空,unique 索引存储的 value 为主键索引,因此二级索引只会占用 writecf 的空间。

  • default 列:用于存储超过 255 字节长度的数据。

内存占用

为了提高读取性能以及减少对磁盘的读取,RocksDB 将存储在 磁盘上的文件都按照一定大小切分成 block(默认是 64KB), 读取 block 时先去内存中的 BlockCache 中查看该块数据是否存 在,存在的话则可以直接从内存中读取而不必访问磁盘。

BlockCache 按照 LRU 算法淘汰低频访问的数据,TiKV 默认将 系统总内存大小的 45% 用于 BlockCache,用户也可以自行修 改 storage.block-cache.capacity 配置设置为合适的值,但 是不建议超过系统总内存的 60%。

写入 RocksDB 中的数据会写入 MemTable,当一个 MemTable 的大小超过 128MB 时,会切换到一个新的 MemTable 来提供写入。TiKV 中一共有 2 个 RocksDB 实例, 合计 4 个 ColumnFamily,每个 ColumnFamily 的单个 MemTable 大小限制是 128MB,最多允许 5 个 MemTable 存 在,否则会阻塞前台写入,因此这部分占用的内存最多为 4 x 5 x 128MB = 2.5GB。这部分占用内存较少,不建议用户自行更 改。

空间占用

  • 多版本:RocksDB 作为一个 LSM-tree 结构的键值存储引擎, MemTable 中的数据会首先被刷到 L0。L0 层的 SST 之间的范围 可能存在重叠(因为文件顺序是按照生成的顺序排列),因此同 一个 key 在 L0 中可能存在多个版本。当文件从 L0 合并到 L1 的 时候,会按照一定大小(默认是 8MB)切割为多个文件,同一 层的文件的范围互不重叠,所以 L1 及其以后的层每一层的 key 都只有一个版本。

  • 空间放大:RocksDB 的每一层文件总大小都是上一层的 x 倍, 在 TiKV 中这个配置默认是 10,因此 90% 的数据存储在最后一层,这也意味着 RocksDB 的空间放大不超过 1.11(L0 层的数 据较少,可以忽略不计)。

  • TiKV 的空间放大:TiKV 在 RocksDB 之上还有一层自己的 MVCC,当用户写入一个 key 的时候,实际上写入到 RocksDB 的是 key + commit_ts,也就是说,用户的更新和删除都是会写 入新的 key 到 RocksDB。TiKV 每隔一段时间会删除旧版本的数 据(通过 RocksDB 的 Delete 接口),因此可以认为用户存储在 TiKV 上的数据的实际空间放大为,1.11 加最近 10 分钟内写入 的数据(假设 TiKV 回收旧版本数据足够及时)。

compact

RocksDB 中,将内存中的 MemTable 转化为磁盘上的 SST 文 件,以及合并各个层级的 SST 文件等操作都是在后台线程池中 执行的。后台线程池的默认大小是 8,当机器 CPU 数量小于等 于 8 时,则后台线程池默认大小为 CPU 数量减一。通常来说, 用户不需要更改这个配置。如果用户在一个机器上部署了多个 TiKV 实例,或者机器的读负载比较高而写负载比较低,那么可 以适当调低 rocksdb/max-background-jobs 至 3 或者 4。

WriteStall(写停顿)

RocksDB 的 L0 与其他层不同,L0 的各个 SST 是按照生成顺序 排列,各个 SST 之间的 key 范围存在重叠,因此查询的时候必 须依次查询 L0 中的每一个 SST。为了不影响查询性能,当 L0 中的文件数量过多时,会触发 WriteStall 阻塞写入。

如果用户遇到了写延迟突然大幅度上涨,可以先查看 Grafana RocksDB KV 面板 WriteStall Reason 指标,如果是 L0 文件数 量过多引起的 WriteStall,可以调整下面几个配置到 64。

rocksdb.defaultcf.level0-slowdown-writes-trigger 
rocksdb.writecf.level0-slowdown-writes-trigger 
rocksdb.lockcf.level0-slowdown-writes-trigger 
rocksdb.defaultcf.level0-stop-writes-trigger 
rocksdb.writecf.level0-stop-writes-trigger 
rocksdb.lockcf.level0-stop-writes-trigger 

参考连接:https://github.com/0voice

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/91651.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/91651.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PTE之路--01

空格绕过:/**/ URL编码伪协议:pagezip://xxx/xx/x/x/xxx.jpg%23解压后的名字pagephar://xxx/xx/x/x/xxx.jpg/解压后的名字pageddata://ata://text/plain,<?php eval($_POST[x]) ;?>pagedata://text/plain,<?php eval($_POST[x]) ;?>127.0.0.1 | grep . ../key…

企业级日志分析系统ELK

1.什么是 Elastic Stack 如果系统和应用出现异常和问题,相关的开发和运维人员想要排查原因,就要先登录到应用运行所相应的主机,找到上面的相关日志文件再进行查找和分析,所以非常不方便,此外还会涉及到权限和安全问题,而ELK 的出现就很好的解决这一问题。 ELK 是由一家 …

ai项目多智能体

手把手教你构建一个 本地化的&#xff0c;免费的&#xff0c;企业级的&#xff0c;AI大模型知识库问答系统 - 网旭哈瑞.AI 体验 AutoGen Studio - 微软推出的友好多智能体协作框架_autogenstudio-CSDN博客 AutoGen Studio: Interactively Explore Multi-Agent Workflows | Au…

【HTML】浅谈 script 标签的 defer 和 async

The async and defer attributes are boolean attributes that indicate how the script should be evaluated. There are several possible modes that can be selected using these attributes, depending on the script’s type. async 和 defer 属性是布尔属性&#xff0c;…

Kafka Streams 并行处理机制深度解析:任务(Task)与流线程(Stream Threads)的协同设计

在构建实时流处理应用时&#xff0c;如何充分利用计算资源同时保证处理效率是一个关键问题。Kafka Streams 通过其独特的任务(Task)和流线程(Stream Threads)并行模型&#xff0c;为开发者提供了既简单又强大的并行处理能力。本文将深入解析 Kafka Streams 中任务与线程的协同工…

使用 Docker 部署 Label Studio 时本地文件无法显示的排查与解决

目录 使用 Docker 部署 Label Studio 时本地文件无法显示的排查与解决 1. 背景 2. 问题现象 3. 排查步骤 3.1 确认文件是否存在 3.2 检查环境变量配置 4. 解决方案 方法一&#xff1a;修改 Sync Storage 路径&#xff08;相对路径&#xff09; 方法二&#xff1a;修改…

ElasticJob怎么使用?

我们使用ElasticJob需要以下步骤&#xff1a; 1. 添加依赖 2. 配置任务&#xff08;可以使用Spring命名空间配置或Java配置&#xff09; 3. 实现任务逻辑&#xff08;实现SimpleJob、DataflowJob等接口&#xff09; 4. 启动任务 下面是一个详细的示例&#xff0c;包括Spring Bo…

TCP协议的特点和首部格式

文章目录TCP协议是什么&#xff1f;TCP协议的主要特点1. 面向连接2. 可靠传输3. 流量控制4. 拥塞控制TCP首部格式源端口和目标端口&#xff08;各16位&#xff09;序列号&#xff08;32位&#xff09;确认号&#xff08;32位&#xff09;数据偏移&#xff08;4位&#xff09;保…

IO流-文件的常用方法

1.关于java.io.File类- File类只能表示计算机中的文件或目录而不能获取或操作文件- 通过File类获得到文件的基本信息&#xff0c;如文件名、大小等&#xff0c;但不能获取文件内容- java中表示文件路径分隔符使用"/"或"\\"- File类中的构造方法- File(&quo…

AUTOSAR进阶图解==>AUTOSAR_SRS_E2E

AUTOSAR E2E通信保护解析 AUTOSAR End-to-End通信保护机制详解与应用目录 概述 1.1. AUTOSAR E2E通信保护的作用 1.2. E2E通信保护的应用场景AUTOSAR E2E架构 2.1. E2E组件层次结构 2.2. E2E库和E2E转换器E2E监控状态机 3.1. 状态定义与转换 3.2. 状态机实现E2E保护数据交换流…

镜像快速部署ollama+python+ai

算力租赁入口&#xff1a;https://www.jygpu.com为大家提供以上镜像快速部署方式&#xff0c;节约大家环境部署时间一键部署的便捷性传统自建GPU服务器需要经历复杂的硬件采购、驱动安装、环境配置等繁琐步骤&#xff0c;而现代​​GPU租赁价格对比​​显示&#xff0c;容器化平…

使用Gemini API开发领域智能聊天机器人的思路

以下是使用 Gemini API 开发软件自动化测试专家领域专属智能聊天机器人的详细思路及具体实现过程&#xff1a; 阶段一&#xff1a;基础准备与规划 (Foundation & Planning) 这个阶段的目标是明确方向、准备好所有必要的工具和凭证。 步骤 1&#xff1a;明确聊天机器人的目…

第13届蓝桥杯Python青少组_省赛_中/高级组_2022年4月17日真题

更多内容请查看网站&#xff1a;【试卷中心 -----> 蓝桥杯----> Python----> 省赛】 网站链接 青少年软件编程历年真题模拟题实时更新 第13届蓝桥杯Python青少组_省赛_中/高级组_2022年4月17日真题 一、选择题 第 1 题 下列二进制数中最大的是&#xff08; &a…

sqli-labs:Less-17关卡详细解析

1. 思路&#x1f680; 本关的SQL语句为&#xff1a; $sql"SELECT username, password FROM users WHERE username $uname LIMIT 0,1"; $update"UPDATE users SET password $passwd WHERE username$row1";注入类型&#xff1a;字符串型&#xff08;单引号…

文心一言:推动 AIGC 领域进步

文心一言:推动AIGC领域进步 关键词:文心一言、AIGC、自然语言处理、多模态生成、大模型、技术架构、应用场景 摘要:本文深入剖析百度文心一言在AIGC(人工智能生成内容)领域的技术创新与实践成果。通过解析其核心技术架构、多模态生成原理、工程化落地策略及行业应用案例,…

第15讲——微分方程

文章目录思维导图基本概念微分方程及其阶思维导图 基本概念 微分方程及其阶

RAGFlow Agent 知识检索节点源码解析:从粗排到精排的完整流程

RAGFlow Agent 知识检索节点深度解析&#xff1a;从查询到重排序的完整流程 1. 总体架构概览 RAGFlow Agent 中的知识检索&#xff08;Retrieval&#xff09;节点是整个RAG系统的核心组件&#xff0c;负责从知识库中找到与用户查询最相关的文档片段。检索流程可以分为以下几个…

Python算法实战:从排序到B+树全解析

Python中常见的算法示例 以下是Python中常见的算法示例,涵盖基础算法和经典问题解决方案,代码可直接运行: 排序算法 冒泡排序 def bubble_sort(arr):n = len(arr)for i in range(n):for j in range(0, n-i-1):if arr[j] > arr[j+1]:arr[j], arr[j+1] = arr[j+1], arr…

【C++算法】85.BFS解决最短路径问题_最小基因变化

文章目录题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a;题目链接&#xff1a; 433. 最小基因变化 题目描述&#xff1a; 解法 先看懂题目 先把这个问题转化&#xff1a;图论问题 边权为1的最短路问题。 为什么可以这么想&#xff1f;&#xff01; 因为每…

基于单片机汽车少儿安全预警系统

文章目录一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】项目硬件模块组成【4】设计意义【5】市面上同类产品研究现状【6】摘要1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】设备端开发【2】上位机开发1.5 模块的技术详情介绍1.6 框架图框架图说明&…