写点什么

一文读懂 GaussDB(for Mongo) 的计算存储分离架构

  • 2020-08-17
  • 本文字数:2722 字

    阅读完需:约 9 分钟

一文读懂GaussDB(for Mongo)的计算存储分离架构

1.摘要

GaussDB(for Mongo)是华为云自主研发兼容 MongoDB4.0 接口的文档数据库。基于共享存储的存算分离架构,对于传统 MongoDB 社区版有如下优势:


  • 秒级添加 Secondary 节点(相比社区版 Mongo 小时级添加 Secondary 节点)

  • 基于 WAL 复制, Secondary 节点无写 IO,从根本上解决社区版 Seconary 节点 Oplog 脱节问题

  • Primary/Seconary 无任何 IO 交互,Secondary 节点个数理论无上限, 支持百万 OPS 的读事务能力

  • LSMTree Compaction 计算/IO 卸载到 Compaction 统一调度池,集中管理,不浪费用户读写 IO

  • 基于共享存储,Chunk 分裂/迁移动作不引起真实 IO,只更新路由元数据,秒级分裂/均衡

2.GaussDB(for Mongo)技术架构

1)容忍更多 Shard 宕机


与社区版 MongoDB 的Share-Nothing模式不同的是,GaussDB(for Mongo)采用Share-Storage架构,计算存储分离。集群模式下,N 个 Shard 节点,可以容忍 N-1 个 Shard 宕机。



某个 Shard 节点宕机后,其负责的数据由于存在于共享的存储池中,因此不需要物理拷贝数据,只需要修改元数据路由信息,即可被其他分片节点接管。


2)更快的分裂与均衡能力


此外,由于 Chunk 数据在存储池中,Chunk 的分裂与均衡不涉及到数据拷贝,可以做到分钟级分裂与扩容,分裂与扩容对用户的影响也远比社区版 MongoDB 小。



3)百万级读 OPS 能力


GaussDB(for Mongo)副本集模式下,Primary/Secondary 节点之间共享同一份数据库文件。Secondary 节点只复制 Primary 节点的 WriteAheadLog 以及 LSMTree 的结构变更信息,并应用到内存中。Secondary 节点没有 LSMTree 的 Compaction 和 Flush 任务,因此对用户的读业务影响很小。



此外,由于Share-Storage的架构优势,添加 Secondary 节点并不需要拷贝数据,添加 Secondary 节点的动作可以秒级完成。而 Primary/Secondary 之间只传递元数据变更,不传递 WriteAheadLog,因此 Secondary 节点的个数即使变多,也不影响 Primary 节点的写性能。Secondary 节点可以水平扩展,支撑百万级的读 OPS。


4)主节点 IO 卸载


LSMTree 的写压力来源于三部分:


  • 用户的业务写入导致的 Memtable Flush

  • 后台 SST 文件 Compaction

  • WAL 的持续写入


根据线上业务的实际测算,三者的 IO 资源消耗占比为: 1:10:1。后台的 SST 文件 Compaction 占了绝大部分 IO 带宽,通过将 Compaction 任务集中化管理,从计算池卸载到存储池,进一步减少了用户计算节点的 CPU 和 IO 资源消耗。



5)GaussDB(for Mongo) 只读节点设计


  • 传统社区版 MongoDB 副本集基于 Oplog 做数据复制,只读节点需要镜像主节点的所有写 IO 操作。GaussDB(for Mongo) 的只读节点和主节点共享同一份底层数据库文件(LSMTree 的 SST 文件),只读节点并不自己生成 SST 文件。

  • 随着业务数据的写入,Compaction 的不断执行,LSMTree 的当前版本(包含哪些 SST 文件)不断更新,LSMTree 的元数据更新(增删 SST 文件的记录)被同步到只读节点执行。

  • RocksDB 中,数据的变更被持久化到 WAL 里,元数据的变更(增删文件的操作, 叫做 VersionEdit)被持久化到 Mainifest 里。RocksDB 的数据和元数据是分开的,WAL 流和 VersionEdit 流是并行的,没有严格的先后顺序。为了保证只读节点和主节点完全一致的事件回放顺序,WAL 和 VersionEdit 流必须要合并成一个流,在双流合并后,通过 LSN 就可以为每个事件(WAL 的写操作/VersionEdit)定序。



  • 基于 WAL+VersionEdit 复制,而不基于 Oplog 复制

  • 共享文件(sst/wal)的生命周期管理由主节点负责 sst 文件和 wal 的文件的生命周期由主节点负责。RocksDB 中,SST 文件通过层级的引用计数来维持不被删除。如下图,RocksDB 的每个游标会维持 SuperVersion,如下图中的 S0,S1,S2。每个 SuperVersion 会引用一个 Version,一个 Version 代表 LSMTree 在不断变形(通过增删 SST 文件变形)的过程中,某个时间点的形状,最新的 Version 就代表 LSMTree 当前的形状。



  • 在 GaussDB(for Mongo)中,主节点会记录所有只读节点在使用的 Version,并为这些 Version 增加引用计数从而维持 SST 文件的生命周期。对于 WAL,主节点会记录所有只读节点中最老的 LSN(oldestLsn),最老的 LSN 来自于复制最慢的只读节点。并删除比 oldestLsn 还旧的 WAL 文件。

  • 元数据变更通知,无论是 oldestLsn 还是只读节点的当前在用的活跃的 Version,都需要及时推进,这些元数据的变更是通过主从节点的定期心跳上报到主节点上的。主节点利用心跳数据对垃圾版本与 WAL 做清理。如下图所示,在经历一次心跳后,主节点发现 Secondary0 的 Version0 和 Secondary1 的 Version0 不再使用。删除这两个 Version 后,SST0 的引用计数为 0,表示 SST0 可以被删除。OldestLsn 也从 100 推进到了 250,可以清理掉 250 之前的 WAL。



  • 只读节点的 memtable 的释放:主节点的 Memtable 不会实时 Flush 为 SST 文件。如果只读节点不处理主节点的 Memtable 的话,只读节点的数据就不是实时的,且存在数据一致性问题。只读节点通过回放 WAL 到内存的 Memtable 中,来覆盖 SST 文件与主节点的 Memtable 的 Gap。上文介绍了只读节点是不往共享存储写入数据的, 所以只读节点上的 Memtable 最后的结局一定是被丢弃掉。但什么时候丢弃这个 Memtable 就是一个问题。过早的丢弃,会造成 SST 文件与 Memtable 之间的数据不连续,存在 Gap,过晚的丢弃会造成内存的浪费。只有当只读节点识别到 SST 的数据已经完全能够 Cover 某个 Memtable 时,这个 Memtable 才可以被丢弃。

  • GaussDB(for Mongo)的只读节点在每次应用 VersionEdit 后,检查所有 SST 中的最大的 LSN 与 Memtable 的最小的 LSN 的关系,来决定是否要丢弃某个 Memtable。

  • 内存元数据的反向更新:传统的复制,数据流从 Oplog 来,走一遍完整的数据库 Server 层 CRUD 接口,再落到引擎层。这种逻辑和主节点上业务的写入逻辑是一致的,因此 Server 层的一些内存元数据结构,在这个过程中就自然而然的得到更新了。但是当采用基于 WAL 的复制后,整个 WritePath 并不经过只读节点的 Server 层。因此 Server 层的内存元数据更新,就是一个很大的挑战。在这里,只读节点对每一条 WAL 做分析,如果 WAL 的内容会影响 Mongo 内存元数据,就会 reload 对应的元数据模块。


3. 总结

GaussDB(for Mongo) 基于 Share-Storage 架构,实现秒级 Chunk 分裂与均衡,对业务影响更小,水平扩展速度更快,能容忍更多节点宕机。只读节点功能,实现了一份数据多计算节点共用的功能。极大的提升了存储的利用效率,提高了计算节点的读取数据能力。为了让副本节点具有持续的读扩展能力,整个只读方案采用元数据的同步模式,在不降低主节点负载的情况下,极大的提升了整个系统的读数据的处理能力。为 3 节点,5 节点,乃至于 15 节点以上的副本集的工作提供了可能。


2020-08-17 10:142554

评论 2 条评论

发布
用户头像
rocksdb 的WAL应该是逻辑日志,不像mysql 的redo log这种物理日志,就无法做到在存储节点层直接进行recovery 吧
2021-02-01 17:21
回复
用户头像
但是在图3里有4条从计算节点到存储节点的path,oplog, wal, data都下沉? 这还是 log is database 吗?

基于 WAL+VersionEdit 复制,而不基于 Oplog 复制

2021-02-01 17:18
回复
没有更多了
发现更多内容

记录一次解决Maven依赖冲突的过程

Java maven

AIGC产业研究报告2023——语言生成篇

易观分析

智能 制造

四大关键举措!高效管控企业税务风险

用友BIP

税务

阿里自爆性能优化100+小技巧,Github已获赞68.7K

Java 性能优化 性能调优

阿里Java面试脑图 被曝光!GitHub上已获赞79.6K

Java java面试 Java八股文 Java面试题 Java面试八股文

开箱即用!AI模型库全新发布,一站式在线开发部署!

飞桨PaddlePaddle

模型 飞桨

GitHub笔记疯抢竟崩溃!Redis完整开发实战居然包含大厂同款项目

Java你猿哥

Java redis ssm java面试 Redis 核心技术与实战

阿里云数据库ClickHouse产品和技术解读

NineData

MySQL 数据库 运维 Clickhouse 2023云数据库技术沙龙

Rhino 7 中文:建模渲染一站式完成~

真大的脸盆

Mac 3D Mac 软件 三维建模 建模软件

研发效能管理中的经典度量——DORA 指标

LigaAI

DevOps 敏捷开发 研发管理 研发效能管理 企业号 5 月 PK 榜

高效联调,可靠发布!华为云推出CodeArts Release发布管理服务

华为云开发者联盟

云计算 开发工具 华为云 华为云开发者联盟 企业号 5 月 PK 榜

使用doop识别最近commons text漏洞的污点信息流

vivo互联网技术

SAST commons text命令执行漏洞 doop

23年最新Java岗常见面试题及答案(1000道),90% 的公司都会问到

Java你猿哥

Java MySQL zookeeper JVM java面试

使用 Python 和 mitmproxy 实现基于队列的路径管理

IT蜗壳-Tango

本周精彩!关于 Linux 内核宕机和超融合 Kata 虚拟化容器技术介绍 | 第 77-78 期

OpenAnolis小助手

开源 云原生 系统运维 龙蜥大讲堂 浪潮

Java开发实践:合理使用线程池及线程变量

阿里技术

Java 线程池

百万年薪大佬甩出的SpringBoot趣味实战手册,GitHub标星81.6K

Java你猿哥

redis spring Spring Boot Spring MVC 消息队列对比

玩转Netty,从“Hello World”开始!

Java你猿哥

Java Netty ssm

SecureCRT中文乱码怎么办?解决 SecureCRT中文乱码方法

互联网搬砖工作者

GitHub爆赞!阿里P9纯手打十亿级高并发系统手册,真的太香了!

Java 系统设计 高并发 亿级并发

Python从零到壹丨详解图像锐化Roberts、Prewitt算子实现边缘检测

华为云开发者联盟

人工智能 华为云 图像 华为云开发者联盟 企业号 5 月 PK 榜

volatile 关键字与计算机底层的一些杂谈

Java你猿哥

Java volatile JVM ssm java知识点

SVN管理工具Cornerstone入门教程

互联网搬砖工作者

首个支持RWA交易的订单簿DEX-PoseiSwap,即将开启IEO

鳄鱼视界

阿里首席架构师讲解“双十一”亿级流量高并发的系统架构搭建方法

Java 系统设计 高并发 亿级流量

极狐GitLab as Code,全面升级你的 GitOps 体验

极狐GitLab

git DevOps 云原生 版本控制 gitops

基于Sentinel自研组件的系统限流、降级、负载保护最佳实践探索 | 京东云技术团队

京东科技开发者

开源 京东云 企业号 5 月 PK 榜

Makefile基础教程:从零开始学习

小万哥

程序员 面试 后端 C/C++ makefile

MobLink 创建应用

MobTech袤博科技

GitHub万赞,不愧是腾讯大牛总结的操作系统笔记,面面俱到太全了

Java你猿哥

Java 面试 多线程 ssm 线程与进程

一文读懂GaussDB(for Mongo)的计算存储分离架构_数据库_华为云与计算_InfoQ精选文章