热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入解析TiDBBinlog:PumpStorage实现详解(上)

本文作者赵一霖,将继续探讨TiDBBinlog系统中PumpStorage的实现细节,包括其核心功能如持久化存储、数据排序及配对等。

作者:赵一霖

在前文中,我们详细讨论了 Pump Server 的启动流程、gRPC API 的实现、服务下线及相关辅助机制,期间多次提及 Pump Storage。本文将聚焦于 Pump Storage 的具体实现,其源代码主要位于 pump/storage 目录下。

Pump Storage 是由 Pump Server 调用的一个模块,主要职责是实现 binlog 的持久化存储,并支持数据的排序与配对。接下来,我们将从 Storage 接口入手,逐步解析 Pump Storage 的内部工作原理。

Storage 接口概述

Storage 接口定义了 Pump Storage 对外提供的主要操作方法,其中包括重要的 WriteBinlogGCPullCommitBinlog 方法。以下是 Storage 接口的定义:

type Storage interface { // 写入 binlog 数据到 Storage WriteBinlog(binlog *pb.Binlog) error // 清理 tso 小于指定 ts 的 binlog GC(ts int64) // 返回最近一次触发 GC 指定的 ts GetGCTS() int64 // 判断所有 P-binlog 是否都与 C-binlog 匹配 AllMatched() bool // 返回最大 CommitTS,在此 TS 之前的数据已完整可同步 MaxCommitTS() int64 // 根据指定 ts 获取 binlog GetBinlog(ts int64) (binlog *pb.Binlog, err error) // 按序拉取 commitTs 大于 last 的 binlog PullCommitBinlog(ctx context.Context, last int64) <-chan []byte // 安全关闭 Storage Close() error }

Append 持久化实现

Append 是基于文件系统的持久化实现,主要负责将 binlog 数据追加写入到 Valuelog 中。考虑到单条 binlog 可能非常大,为了提升性能,我们采用了 Key 和 Value 分离的设计策略,使用 goleveldb 存储 Key(binlog 的时间戳),并设计了专门用于存储 binlog 数据的 Valuelog 组件。

初始化过程

Append 的初始化逻辑在 NewAppendWithResolver 函数中实现,主要包括初始化 Valuelog、goleveldb 等组件,并启动多个 goroutine 以处理 binlog 写入、GC 和状态维护等工作。

WriteBinlog 方法解析

WriteBinlog 方法由 Pump Server 调用,用于将 binlog 数据写入本地持久化存储。在 Append 实现中,binlog 数据在编码后会被送入 Append.writeCh 通道,由专门的 goroutine 处理:

toKV := append.writeToValueLog(writeCh) go append.writeToSorter(append.writeToKV(toKV))

binlog 数据进入 Append.writeCh 后,将依次经过以下几个处理阶段:

  • ValueLog:主要由 writeToValueLog 函数实现,将 binlog 数据批量写入 ValueLog 组件中。ValueLog 是一种持久化的键值存储实现,具体将在后续文章中详细介绍。
  • Metadata:由 writeBatchToKV 函数实现,将 binlog 的时间戳作为 Key,valuePointer 作为 Value 批量写入 Metadata 存储中。当前 Pump 使用 goleveldb 作为 Metadata 存储数据库,其底层数据结构为 LSM-Tree,确保了 binlog 相关信息按时间戳自然排序。
  • Sorter:尽管 binlog 元数据在写入过程中已经排序,但仍需 writeToSorter 进行进一步处理。这是因为 TiDB 事务采用 2PC 算法,每个成功事务包含 Prewrite 和 Commit 两条 binlog;若事务失败,则会生成一条 Rollback binlog。为了准确还原事务,必须对 Prewrite 和 Commit binlog 进行配对。Sorter 负责读取 binlog 并进行配对,对于长时间未找到匹配项的 Prewrite binlog,Sorter 会查询 TiKV 以确认其状态。

PullCommitBinlog 方法解析

PullCommitBinlog 方法用于从客户端指定的时间戳开始拉取 Commit binlog。其实现较为直接,Append 会扫描 Metadata,仅关注 Commit binlog,并根据 StartTs 查找对应的 Prewrite binlog,从而确保拉取到的均为已提交的 binlog。

GC 机制分析

GC 机制是 Pump Storage 中不可或缺的部分,旨在定期清理不再需要的 binlog 数据,以释放存储空间。GC 的触发条件包括:binlog 已同步至下游或其时间戳距离当前时间已超过预设时间。GC 过程分为两个阶段:一是扫描并删除 Metadata 中的旧数据;二是根据删除的 KVS 数量触发 Valuelog 的 GC,最终表现为删除文件系统中的文件。

在实际应用中,为避免 GC 过程对系统性能造成负面影响,我们对 GC 进行了限速处理,例如通过监控 goleveldb 中 L0 文件的数量来决定是否暂停 GC。

总结

本文深入探讨了 Pump Storage 的初始化过程及其核心功能的实现,希望对读者理解 TiDB Binlog 系统有所帮助。下一篇文章将重点介绍 Valuelog 和 SlowChaser 等辅助机制。


推荐阅读
  • Working with Errors in Go 1.13
    作者|陌无崖 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 数据管理权威指南:《DAMA-DMBOK2 数据管理知识体系》
    本书提供了全面的数据管理职能、术语和最佳实践方法的标准行业解释,构建了数据管理的总体框架,为数据管理的发展奠定了坚实的理论基础。适合各类数据管理专业人士和相关领域的从业人员。 ... [详细]
  • 整理于2020年10月下旬:总结过去,展望未来Itistoughtodayandtomorrowwillbetougher.butthedayaftertomorrowisbeau ... [详细]
  • 本文全面解析了 gRPC 的基础知识与高级应用,从 helloworld.proto 文件入手,详细阐述了如何定义服务接口。例如,`Greeter` 服务中的 `SayHello` 方法,该方法在客户端和服务器端的消息交互中起到了关键作用。通过实例代码,读者可以深入了解 gRPC 的工作原理及其在实际项目中的应用。 ... [详细]
  • 本文基于刘洪波老师的《英文词根词缀精讲》,深入探讨了多个重要词根词缀的起源及其相关词汇,帮助读者更好地理解和记忆英语单词。 ... [详细]
author-avatar
Jessica_猪猪到_697
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有