重点内容
在之前的几篇关于 SmartX 分布式块存储 ZBS 架构设计文章中,已对 ZBS 存储的整体架构设计、接入协议 NVMe-oF 和数据同步协议 RDMA 进行了较为全面的介绍。为了帮助用户更好地理解 ZBS 存储底层的设计实现,本篇文章将涉足存储系统中非常重要的组件之一:元数据管理。
元数据是什么?通常得到相对简单的答案是描述数据的数据。这句解释并没有错,但是有些抽象,并不容易理解。元数据本身并不会暴露自己给使用者,仅是为存储系统或文件系统服务,我们可以将元数据想象成过去查公司电话和地址的大黄页或是图书的索引,用于记录数据的存储位置。当用户需要读取或修改某个文件时,这个文件对应存储的具体位置,就是由元数据进行管理的。当然,除了记录存储位置,元数据还会存储一些数据的属性信息,来扩展数据的管理能力,例如数据块什么时间创建、什么时间发生修改、数据块是否需要回收、数据块的操作权限等。
所以,在存储系统内部,元数据管理十分地重要,凡是涉及到存储系统的数据访问,都会经过元数据的查询或更新操作,如果元数据操作出现性能瓶颈,将会严重影响存储系统的性能表现。本文通过多个维度展开介绍元数据管理的现状以及未来的发展趋势,同时分享 ZBS 的元数据设计思想。
最简单的元数据管理 Meta Server(元数据服务)+ Meta DB(数据库):这种方案算是初代经典的设计思想,后续方案在此基础上进行延展。
基于高可用架构的元数据管理:这个方案的前置条件需要部署多节点,合理布局 Master 和 Slave 角色,从而提高节点容错性。
基于内存的元数据管理:Meta Server 通过将元数据全部加载到内存,加速元数据的访问速度,从而满足元数据访问更高的性能要求。由于采用内存加载元数据,在设计上,需要评估数据规模。
在海量数据规模下,单节点内存已不能承载全部的元数据,将元数据分区(分布式架构横向扩展)则是一条主要的技术发展方向:将元数据按照规则进行分拆,通过多个 Meta Server 服务来管理各自维护的元数据。此方案还需要一层路由或代理服务角色,用来处理请求转发。
除元数据横向扩展外,另一条技术方向是分层(Tier Layer)管理元数据,这里称为纵向扩展。设计思想是将热点数据做内存缓存(Cache Layer)、冷数据做持久化保存在磁盘(Persisted Layer),根据算法,实现冷热数据的交换。
设计和管理存储系统的元数据是一个复杂的任务,面临着多个挑战。以下是一些与元数据管理相关的主要挑战:
存储系统的元数据管理涉及到数据量和复杂性、一致性和完整性、性能和可伸缩性、存储和备份、查询和检索、演化和版本管理等多个挑战。解决这些挑战需要综合考虑系统架构、存储技术、数据管理策略等多方面的因素。
ZBS 存储的定位是分布式块存储系统,主要应用场景包括云计算 IaaS、虚拟化、裸金属数据库和容器。基于这些应用场景,ZBS 对元数据管理有如下几个需求:
提及元数据存储,第一个想到的方案就是关系型数据库,例如 MySQL,以及一些成熟的 KV 存储引擎,例如 LevelDB,RocksDB 等。这种类型的存储最大的问题就是无法提供可靠的数据保护和 Failover 能力。LevelDB 和 RocksDB 虽然非常轻量级,但都只能把数据保存在单机上。尽管 MySQL 提供一些主备方案,但 MySQL 的主备方案过于笨重,在故障切换场景中并不灵活,且缺乏简易的自动化运维方案,所以并不是一个十分好的选择。
其他的方案还包括分布式数据库,例如 MongoDB 和 Cassandra。这两种分布式数据库都可以解决数据保护和提供 Failover 机制。但是他们都不提供或不能全面支持 ACID 机制,所以在上层实现时会比较麻烦,需要额外的工作量。其次就是这些分布式数据库在运维上也相对复杂,不是很易于自动化运维。
基于 Paxos 或者 Raft 协议自己实现一个框架?这样实现的代价会非常大,对于一个初创公司并不是一个最佳选择(SmartX 成立时间是 2013 年,当时 Raft 也只是刚刚提出)。
还可以选择 Zookeeper。Zookeeper 基于 ZAB 协议(Zookeeper Atomic Broadcast),可以提供一个稳定可靠的分布式存储服务(崩溃恢复和消息广播),确保事务的一致性。但 Zookeeper 的最大的问题是存储的数据容量非常有限,为了提高访问速度,Zookeeper 把存储的所有数据都缓存在内存中,所以这种方案导致元数据服务所能支撑的数据规模严重受限于服务器的内存容量,使得元数据服务无法做到轻量级,也无法和数据服务混合部署在一起。
最后还有一种方案是基于 DHT(Distributed Hash Table)的路线(很多开源类产品,例如 Ceph,都是基于 DHT 实现)。这种方案的好处即元数据中不需要保存数据副本的存储位置,而是根据一致性哈希的方式计算出来,这样就极大地降低了元数据服务的存储压力和访问压力。但使用 DHT ,就丧失了对数据副本位置的控制权,在实际生产环境中,非常容易造成集群中的数据不均衡的现象。同时在运维过程中,如果遇到需要添加节点、移除节点、添加磁盘、移除磁盘的情况,由于哈希环会发生变化,一部分数据需要重新分布,会在集群中产生不必要的数据迁移,而且数据量往往非常大。而这些运维操作在客户的数据中心几乎每天都会发生。大规模的数据迁移很容易影响到线上的业务的性能,所以 DHT 使得运维操作变得非常麻烦而不可控。
通过以上分析,可以看出,每种技术路线均有各种各样的问题,并不能直接使用。ZBS 采用 Log Replication 的机制,设计上,选择 Raft 可能要优于 ZK,但综合评估实现复杂性和代价,最终选择 LevelDB 和 Zookeeper 相结合,并同时避开他们自身的问题,实现元数据管理服务。
这里简单地介绍一下 Log Replication。简单来说,把数据或者状态看作是一组对数据操作的历史集合,而每一个操作都可以通过被序列化成 Log 记录下来。如果可以拿到所有的 Log,并按照 Log 里面记录的操作重复一遍,那么就可以完整的恢复数据的状态。任何一个拥有 Log 的程序都可以通过重放 Log 的方式恢复数据。如果对 Log 进行复制,实际上也就相当于对数据进行了复制。这就是 Log Replication 最基本的想法。
ZBS 元数据的关键能力设计:
ZBS 元数据服务的具体实现:
ZBS 元数据服务特点:
随着存储系统的不断发展和变化,元数据管理也在不断演化和改进。正如前文对元数据管理技术路线的分析,通过分区(分布式架构)实现元数据管理,可以更好地面对数据激增、架构横向扩展、查询速度提升、降低切换时间等要求与挑战。
元数据在存储系统中发挥着重要的作用,未来的元数据管理也将面临更多的挑战和机遇。通过合理的元数据管理策略和技术实现,可以更好地管理和维护数据,并提高存储系统的可靠性、稳定性和高效运行。
这里留个彩蛋,ZBS 将在下一个大版本更新时进一步优化元数据管理机制,待正式发布后,再分享其背后的思考和设计实现。
想了解更多 ZBS 的架构原理和技术细节?欢迎阅读电子书《分布式块存储 ZBS 的自主研发之旅》。