TiDB 数据库的存储

article/2025/9/21 2:10:57

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

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 的协议,只需要同步复制到多数节点,即可安全地认为数据写入成功。

总结一下,通过单机的 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,并且会尽量保持每个 Region 中保存的数据不超过一定的大小,目前在 TiKV 中默认是 96MB。每一个 Region 都可以用 [StartKey,EndKey) 这样一个左闭右开区间来描述。

注意,这里的 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 之后,应该可以理解下面这张图:

 

以 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 根据这篇论文实现,并做了大量的优化。详细介绍参见事务概览。


http://chatgpt.dhexx.cn/article/3xVxPXnG.shtml

相关文章

TiDB-新一代数据库入门介绍

由于目前的项目计划把MySQL换成TiDB,所以特意来了解下TiDB。其实也不能说换,由于TiDB和MySQL几乎完全兼容,所以我们的程序可以没有任何改动就完成数据库从MySQL到TiDB的转换。接下来了解一下TiDB,为将来的技术选型做个准备。 一、…

TIDB数据库特性总结

文章目录 前言一、TIDB数据库介绍1.1数据管理技术发展阶段1.2 数据库分类1.2 如何学习TiDB 二、TIDB特点和使用场景2.1.MySQL存在问题2.2.TiDB数据库特点2.3TIDB架构特性2.4 TiDB 核心特性2.4.1水平扩展性2.4.2高可用性 2.5 TIDB的存储和计算能力2.6 TIDB特性总结 3 TIDB部署总…

TIDB整体架构

TiDB 集群主要包括三个核心组件:TiDB Server,PD Server 和 TiKV Server。此外,还有用于解决用户复杂 OLAP 需求的 TiSpark 组件和简化云上部署管理的 TiDB Operator 组件。 架构图解 TiDB Server TiDB Server 负责接收 SQL 请求,处…

TIDB简单了解

官方文档 TIDB HTAPTIDB HATP 基础概念: TIDB应用场景(优势)体系结构TIDB的管理及调度-PDTIDB链接层和SQL层-TIDB Server存储节点TIKVKVRocksDBRaft协议主副本选举日志复制 RegionMVCCACID事务 TiFlash HTAP 先为大家推荐一篇文章 https://…

TiDB数据库架构概述

目录 TiDB体系架构 TiDB Server TiKV(行存) PD (Placement Driver) TiFlash(列存) 例题 TiDB体系架构 TiDB Server TiDB Server是无状态的 无状态,指数据不在TiDB中落地,即TiD…

TIDB介绍(二)

参考文章:专栏 - 国产化浪潮下TiDB解决的痛点问题 | TiDB 社区 1 前言 随着国内互联网企业的快速发展,传统的oracle数据库架构在成本和扩展性上已不能满足要求,更多的企业将目光转向了开源的MySQL数据库,由于MySQL本身是一个…

分布式数据库——TiDB的介绍和基本原理

1、TiDB 介绍 1.1 TiDB 介绍 1.1.1 TiDB 是什么? TiDB 是一个分布式 NewSQL 数据库。它支持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和 MySQL 协议,具有数据强一致的高可用特性,是一个不仅适合 OLTP 场景(on-line trans…

15分钟了解TiDB

由于目前的项目把mysql换成了TiDb,所以特意来了解下tidb。其实也不能说换,由于tidb和mysql几乎完全兼容,所以我们的程序没有任何改动就完成了数据库从mysql到TiDb的转换,TiDB 是一个分布式 NewSQL (SQL 、 NoSQL 和 NewSQL 的优缺…

TIDB简介及基础架构

1. 什么是TIDB TiDB 是一个分布式 NewSQL 数据库。它支持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和 MySQL 协议,具有数据强一致的高可用特性,是一个不仅适合 OLTP 场景还适合 OLAP 场景的混合数据库。 1.1 什么是NewSQL SQL,传统关…

(一)TiDB简介

TiDB是PingCAP公司自主设计、研发的开放源分布式关系型数据库(NewSQL),是一个款同时支持在线事务处理与在线分析处理(Hybird Transactional and Analytical Processing,HTAP)的融合型分布式数据库产品。 目标是为用户提供一站式OLTP(Online T…

TiDB原理解析

TiDB是PingCAP公司设计的开源分布式NewSQL数据库。由于它兼容MySQL协议,并支持绝大多数SQL功能(比如joins,subqueries, transaction等)。业务能够直接通过MySQL connector去使用它来替换MySQL。TiDB适合场景: 数据量大…

TiDB 简介(二)

参考:TiDB 简介_福海鑫森的博客-CSDN博客_tidb开发语言 TiDB 简介 | PingCAP Docs TiDB 是 PingCAP 公司自主设计、研发的开源分布式关系型数据库,是一款同时支持在线事务处理与在线分析处理 (Hybrid Transactional and Analytical Processing, HTAP) 的…

TiDB入门+深入

目录 一、概述 1、从MySQL到TiDB 2、简介 1、OLTP和OLAP 3、TiDB整体架构 4、TiDB安装部署 开发及测试环境 生产环境 5、TiDB-读取历史数据 6、数据迁移-TiDB Lightning 一、概述 数据库(DataBase)是按照数据结构来组织、存储和管理数据的仓库…

TIDB简介及TIDB部署、原理和使用介绍

TiDB简介及TiDB部署、原理和使用介绍 从MySQL架构到TiDB 数据库分类 ​ 介绍TiDB数据库之前,先引入使用场景。如今的数据库种类繁多,RDBMS(关系型数据库)、NoSQL(Not Only SQL)、NewSQL,在数…

JAVA注解学习-@Documented注解

这个注解只是用来标注生成javadoc的时候是否会被记录。 用法 在自定义注解的时候可以使用Documented来进行标注,如果使用Documented标注了,在生成javadoc的时候就会把Documented注解给显示出来。 带Documented生成的javadoc 不带Documented生成的java…

DocumentFragment

文章目录 1. 描述2. 使用 1. 描述 DocumentFragments 是DOM节点。通常的用例是创建文档片段,将元素附加到文档片段,然后将文档片段附加到DOM树。在DOM树中,文档片段被其所有的子元素所代替。 因为文档片段存在于内存中,并不在DO…

java 注解示例(@Documented)

java 注解示例(Documented) 作用:生成文档信息的时候保留注解,对类作辅助说明 *************************** 示例 Documented interface B{String value() default "这是一个自定义类"; }B public class MyTest2 {publ…

document.documentElement与document.body

写前端时遇到这两种方法&#xff0c;转载待以后查看。 两种特殊的文档属性可用来访问根节点&#xff1a; document.documentElementdocument.body 第一个属性可返回存在于 XML 以及 HTML 文档中的文档根节点。 第二个属性是对 HTML 页面的特殊扩展&#xff0c;提供了对 <…

@Documented注解作用

Documented注解作用 验证步骤1. 编写 注解 类2. 执行Javadoc命令生成文档3. 查看IService类文档信息4. 取消// Documented 注解 生成文档并查看 总结 验证步骤 1. 编写 注解 类 // 第一个文件 package com.example.zhaohuiweb;import java.lang.annotation.Documented; imp…

document.documentElement 属性

document.documentElement 属性返回文档中的 html 元素。 语法格式&#xff1a; document.documentElement; 示例&#xff1a; var html document.documentElement;console.log(html); 控制台输出&#xff1a; 如果 html 元素缺失&#xff0c;则返回 null。