作者:
何昱晨,小米软件工程师,Apache Pegasus PPMC
贾硕,小米软件工程师,Apache Pegasus PPMC
编辑:
唐彦昭
本文为 Pegasus 受邀参加 ApacheCon Asia 2021 大会分享的演讲稿,介绍了 Pegasus 的架构设计、基本功能、周边生态以及社区建设。
Apache Pegasus 是一个可水平扩展、高性能、强一致的分布式 Key-Value 数据库,在 TB 级数据下有保证 P999 ms 级延时的能力,同时可在用户无感知的情况下弹性伸缩动态扩容。同时还有热备份、冷备份、Bulk Load、Backup Request 等丰富的功能。

在Pegasus系统中, MetaServer 是管理节点,负责元数据管理、配置变更,并参与一致性协议选主流程。ReplicaServer 是数据节点,用户数据将以哈希散列的方式分布在各个 ReplicaServer,通过对应的 RocksDB 实例完成落盘。Pegasus 采用 PacificA 协议保证副本间数据的强一致性,Zookeeper 用于管理节点的选主与集群元信息的存储。Pegasus 客户端在第一次访问集群时会访问 MetaServer 获取路由表,然后直接与 ReplicaServer交互。Pegasus 采用 hashkey、sortkey 的二级索引 Key-Value 存储数据模型,hashkey 作为一级索引用于 hash 分片,每个 hashkey 下可拥有多个 sortkey,sortkey 以字典序存储。相同 hashkey 的数据存储在同一分片中,这种数据模型设计可以使得我们针对同一 hashkey 下的数据支持原子批量读写。

Pegasus 采用了特殊的双 WAL 写入方案来保证低延迟写入。在传统的解决方案中,数据和WAL被部署在相同的磁盘,客户端写数据时,会先写到 WAL 中,再写入存储引擎,而数据盘的 Compaction 操作以及其他大量的随机读写,会增加 IO 负载,严重影响到 WAL 同步写的性能,进而影响写性能。在实践中,部署 Replica 的机器往往有多块磁盘,Pegasus 使用其中一个磁盘专门存储 WAL,以避免数据盘的高负载带来的写入抖动。但是,如果所有分片的 WAL 都存储在一起,则将花费大量时间进行负载均衡或故障恢复。所以,Pegasus 选择了双 WAL 架构,写请求会先同步写入shared log作为WAL,再同步写入 RocksDB 实例,同时异步写入各个分片的 private log以用于负载均衡和故障恢复。这种设计在实践中能有效减轻长尾延迟并避免负载均衡及故障恢复的低效率问题。

热备份
Bulk Load 用于快速导入大量数据。由于其本质是数据文件的批量加载,相较于传统的逐条写入导入方式能够大幅提高数据灌入速度。首先,用户可以通过 Pegasus-Spark 将原始数据转换为 Pegasus 能够识别的 SST 文件,存储到远程文件系统。生成文件后,Pegasus 服务端将这些文件下载到 ReplicaServer 上,然后将它们快速加载到 Pegasus 表中。
Access Control

与 Hadoop 系统一样,我们使用 Kerberos 进行身份验证。当集群打开访问控制时,客户端使用 keytab 文件完成鉴权。Pegasus 现在使用基于表级访问控制的白名单,在图示的这个例子中,客户端只能访问表 A,不能访问表 B。
Partitrion Split

接下来我们介绍一下 Pegasus 周边生态以及社区建设相关的主题。众所周知,系统的核心部分提供了最主要的功能特性,为了更好的发挥和强化 Pegasus 的能力,我们同时开发和提供了丰富的周边生态工具。
Pegasus-Spark

首先要介绍的就是 Pegasus-Spark,它提供简单易用的连接 Spark 的功能,利用 Spark 强大的分布式处理能力,能够快速构建一个 Spark 任务。Pegasus-Spark 是利用 RocksJava + JNI 开发的一个 HDFS 环境下的 SST 文件读写 Connector。其中,两个最重要的场景就是离线分析能力和离线加载数据的能力。离线数据分析,目的是提供数据的统计分析能力。用户首先需要利用数据导出工具在 HDFS 上生成离线快照,随后使用Pegasus-Spark连接该快照数据。用户既可以直接使用 SparkSQL 构建分析任务,也可以生成 Parquet 文件导入到 Hive 进行更加方便快捷的统计分析。离线数据加载,目的是为了 Pegasus 的 Bulk Load 功能而开发的。如前面描述的那样,Bulk Load 的离线加载需要从远程文件系统直接下载转换好的SST 数据文件,然而 SST 数据文件的生成需要严格的规则保证:首先,待生成的数据必须是去重的;然后,它的分区个数必须和目标表的分片数目一致;最后,也是最重要的,所有的分区内数据必须是有序的。而去重-分区-排序恰好是 Spark 擅长的能力,因此基于 Spark,我们可以很快的构建一个数据转换任务生成 SST 文件并被 Bulk Load 所使用。
Meta Proxy

随后,我们要介绍的就是 Meta Proxy,它本质上是 Pegasus MetaServer 的连接代理。Meta Proxy 主要目标是屏蔽不同业务对不同集群的感知,以提供一个统一的接入入口。这样做可以带来很多好处:首先,不同的客户端不用再维护不同的集群的地址了;然后,由于屏蔽了 MetaServer 的地址, MetaServer 节点的任何变更将变得透明而不再需要通知客户端。

这些特性带来的一个显著优点就是:对于使用热备开启主备集群的用户,当主集群出现故障宕机后,Meta Proxy 可以透明的切换主备集群,以增强系统的容灾能力。
磁盘数据迁移工具

我们最后要推荐给大家的是磁盘数据迁移工具。随着数据不断的写入,对于使用多磁盘卷的部署架构来说,磁盘的使用不均极易导致分布式存储的容量瓶颈。在以前,我们往往因为单盘的使用量告警而不得不添加新的节点,这不仅增加了成本,而且由于节点间的分片迁移并不考虑磁盘容量,所以有时候收效甚微。磁盘数据迁移工具提供了在线的磁盘均衡能力,它首先选择使用量最大的两个磁盘,然后选中符合要求的待迁移分片,随后执行分片迁移。在这个过程,服务端的分片需要经过拷贝->关闭->注册新路径->数据同步等一系列分片变更流程,好在这个过程对用户是透明的,用户基本不会感受到它带来的影响。

Pegasus 最初在 2015 年立项和调研,并在一年后发布了第一个内部版本。2017 年,我们开源了稳定版本 1.7.0,并在随后的 2020 年加入 Apache 基金会成为孵化器项目。同年 9 月,我们发布了更为稳定和完善的 2.0.0 版本,基本涵盖了此次演讲的绝大部分特性。另外有一个好消息是,我们即将在今年 9 月举行 Pegasus Meetup,到时候会分享更多的关于分布式存储设计背后的事情。社区的活跃性是我们关注的一个重点,为促进开源爱好者加入并共建 Pegasus 社区,我们建议贡献者可以从工具集开发入手,包括 client、shell 等一系列增强工具。在未来我们会继续强化 Pegasus 现有功能的稳定性,同时提供更加完善的新功能,如集群级别的均衡功能,以及探索上云的可能。
Pegasus 公众号二维码

关注 Pegasus 公众号二维码,并加入 Pegasus 用户群,获取更多技术内幕与用户支持。










