编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

可以跑数据库的分布式文件系统FastCFS简介

wxchong 2024-08-19 23:54:13 开源技术 6 ℃ 0 评论

一. 概述

FastCFS 是一款基于块存储的通用分布式文件系统,可以作为MySQL、PostgresSQL、Oracle等数据库和云平台的后端存储。

已经有了比较受欢迎的FastDFS,为啥还要研发FastCFS呢?FastDFS是轻量级的对象存储,只能通过专有API访问,为互联网应用量身定制,适合存放图片、视频、文档等等;而FastCFS是通用的分布式文件系统,可以mount到本机通过标准文件接口访问,为云平台量身定制,完全支持数据库。一句话总结:FastCFS是云原生分布式文件系统,保证数据强一致,比FastDFS更加通用和可靠。

为什么业界没有使用分布式文件系统跑数据库的惯例呢?FastCFS作者认为主要原因是现有分布式文件系统要么不支持数据库,要么支持得不好。因为数据库是IO密集型软件,对IO性能要求很高,并且对数据一致性要求非常严苛。FastCFS在保证数据强一致的前提下,同时做到了高性能,完全满足数据库对IO性能和数据一致性的严格要求。软件本身不应该成为系统的性能瓶颈,这是作者我奉行的原则并一直为之实践。

FastCFS完全自主研发(原生实现),除了依赖libfuse实现文件挂载外,不依赖任何第三方软件。FastCFS依赖的基础库libfastcommon来自FastDFS,目前非常成熟和稳定。




二、核心组件及访问方式

FastCFS 是一款可以跑数据库的轻量级分布式存储系统,它为数据库和云平台提供后端存储,保证数据强一致性,解决大容量数据存储问题,做到了高可靠、高可用、高性能以及高扩展性。

FastCFS服务端两个核心组件是 FastStore 和 FastDIR。FastStore是基于块存储的分布式数据存储服务,其文件block大小为4MB,文件 inode + 文件偏移量 (offset)作为block的key,对应的文件内容为 value,FastStore本质是一个分布式Key-Value系统。FastDIR是高性能分布式目录服务,管理文件元数据,支持命名空间。命名空间用于隔离不同应用的文件目录结构,各个应用可以使用自己专属命名空间。若多个应用之间要共享文件目录结构,只需使用相同的命名空间即可。

FastCFS提供了三层访问方式(接口),如下图所示:

最上层是标准文件接口和对象存储接口,其中基于FUSE的标准文件接口已经实现。可以使用FastCFS的fused模块mount到本地,为数据库、虚拟机以及其他使用标准文件接口的应用提供存储。

中间层是FastCFS提供的文件操作API,提供了 fcfs_api_open、fcfs_api_read、fcfs_api_write等函数(对应标准的open、read和write等)。使用此类接口,可以在用户态直接访问FastCFS分布式文件系统。在追求极致性能的场景,可以使用此类接口,比如数据库厂商、分布式计算平台厂商等等。

最下层的FastStore API提供了文件块操作API,包括fs_api_slice_write、fs_api_slice_read、fs_api_slice_delete 等函数。如果不打算使用FastCFS提供的文件元数据管理(即FastDIR组件),可以直接使用此类API。通过调用本层API,FastCFS可以对外提供块设备,比如提供iSCSI接口(目前暂未支持,后续可以考虑支持)。




三、FastStore架构及特点

FastDIR和FastStore均采用Master/Slave结构,Master不需要手工配置,由程序自动选举产生,并且做到了failover。FastDIR架构是FastStore架构子集(特例)。下面是FastStore的架构图:

FastStore对服务器和数据均采用分组方式,服务器分组简称 SG,为物理分组;数据分组简称 DG,为逻辑分组。FastStore的server各自管理数据块(文件块)索引,数据块的元数据采用无中心的分布式架构。FastStore本质是一个分布式KV系统,key是数据块所属的对象ID(inode) + 偏移量(offset),value是数据块内容。FastStore采用的数据路由规则:数据块key按数据分组数(DGC)求模得出所在的数据分组,即:block_hash_code % DGC。可见DGC一旦确定就不可更改,否则将导致数据访问混乱!如果数据增长远超预期需要增大DGC,只能搭建一套新集群,在新旧两套集群并存的情况下,把原有数据手工迁移到新集群,迁移完成后切换到新集群。

一个SG由一台到多台服务器组成,组内的数据是冗余关系(服务器数即数据副本数)。一个SG可以容纳多个DG,为了充分利用CPU等硬件资源,建议生产环境一个SG配置的DG数量不少于CPU核数 / 2,开发测试环境至少配置16个。建立FastCFS集群时,可以只有一组服务器(即一个SG)。为了便于以后增加SG进行扩容,DG数量(DGC)必须事先充足地预估数据规模后确定下来,生产环境建议最小配置 256。友情提示:尽可能乐观地预估数据增长规模,宁多勿少,不存在过犹不及的问题。

FastStore服务器扩容采用数据分裂的做法,支持在线扩容,可以一次扩容一组服务器。当集群规模较小(比如SG数 <= 4)时,建议一次扩容一倍。

总结一下FastStore的架构特点:

  • 基于数据块的无中心设计(类一致性Hash),理论上可以无限扩容;
  • 分组方式(SG和DG),简单高效;
  • 数据分组内采用Master/Slave结构,简单有效的数据一致性保证。




四、数据一致性模型

1.基础结构

说到数据一致性,大家会想到分布式系统必须符合CAP理论:一个分布式系统,不可能完全满足CAP,只能做到其中的两个,即 CA、AP或CP。

FastCFS的目标是支持跑数据库,保证数据一致性是基本要求;保证可用性也是分布式系统的一个基本要求,因此FastCFS选择全力做到 CA,弱化P但不是放弃P。严重的网络分区会破坏数据一致性和系统可用性,通常需要人工介入处理异常数据。FastCFS有数据校验和脑裂修复机制,如果短暂的网络分区没有导致数据不一致的话,FastCFS完全可以自愈。FastCFS的leader和master不是基于中心节点,而是以服务器分组为单元自洽的。由此可见FastCFS在架构和实现机制上采用分而治之的局部化做法,最大程度地规避了发生网络分区的风险。

FastCFS对数据分组采用master/slave结构,对于服务器分组采用leader/follower结构。细心的朋友会有这样的困惑:FastCFS居然有leader和master两种角色,只要其中一种不就可以了吗?二者都是大家所熟知的概念,我相信业界一定有leader + master的做法,但将二者并存于一组服务器,并且以原生方式实现,也许是FastCFS的独创。

FastCFS采用的是数据强一致模型,客户端的更新操作只能在master上执行,然后master通过RPC调用将更新操作同步给ACTIVE状态(此状态方可提供在线服务)的slave。因服务重启或网络严重抖动等异常导致slave掉线,slave将进入数据恢复阶段,追上master的数据后,才能切换为ACTIVE状态。

那么引入 leader/follower目的何在呢?因为一组服务器上通常会包含多个数据分组(为了便于集群扩容会预分配较大的数据分组,比如1024个;一组服务器上配置的数据分组建议不少于64个),每个数据分组的master选举如果按照选举流程来一遍,这个消耗太大。因此FastCFS创新地引入leader角色,由leader直接任命其管辖的若干个数据分组的master。一句话总结leader和master的产生机制:leader通过组内服务器选举产生,而master则由leader直接任命。


2.同步复制机制原理和关键点

和单机系统相比,分布式系统因网络通信方面存在较大不确定性,要做到数据强一致的挑战非常大。业界分布式系统主流做法是采用BASE理论,有意避开数据强一致性这个难题。BASE理论是Basically Available(基本可用),Soft State(软状态或中间状态)和Eventually Consistent(最终一致性)三个短语的缩写。BASE理论比较偏工程实践,见文知意,需要进一步了解的朋友自行脑补。

采用Master/Slave结构,保证数据强一致的逻辑很简单。client的更新操作只能由Master处理,然后master同步调用slave转发该请求。FastCFS中master可以并发请求多个slave,因此client的响应时间和slave数目(副本数)并不是线性关系。master只会对在线(ACTIVE)的slave发起同步调用,那么slave因重启服务或网络通信异常导致掉线(OFFLINE),FastCFS是如何处理的呢?OFFLINE状态的slave会进入数据恢复(追加数据)阶段,追上master的最新数据后,方可切换为ACTIVE状态。为了确保平滑切换,引入了ONLINE这一中间状态。

有朋友就说了,上面的同步复制方式很简单直接嘛,并没有多么高深的地方。嗯,简单的往往就是最有效的。有挑战的地方不在方案的复杂性,而在于工程实现。在保证数据一致性前提下,数据同步复制方案的两大关键点:维护精准的集群状态和slave状态平滑切换。

FastCFS引入leader/follower这一机制来维护精准的集群状态。leader通过选举产生,follower和leader建立连接并每秒报告其自身状态(磁盘空间、数据版本号等)。当集群状态发生变化时,如master切换、slave状态变化等,leader会立即将变动消息推送给所有follower。借助zookeeper或者etcd也可以实现同样的功能,为什么要自造轮子呢?原因有二:一、自主可控,减少依赖;二、简单高效,避免臃肿。




五、简洁高效的访问权限控制

为了更好地对接虚拟机和K8s,FastCFS V2.0主要实现了存储池和访问权限控制,并支持配额。

V2.0支持的核心功能就是用户和权限体系。对于应用系统来说,权限管理是基本功能,实现起来根本就不是事儿。对于基础软件来说,为了保证高性能且不依赖第三方组件,挑战大了不少,其实现方案需要精心设计,实现细节需要仔细推敲。

对一个存储系统来说,把用户、存储池和访问权限相关数据保存到诸如mysql数据库中,当然是可行的,但不讲究,原因如下:一、引入第三方存储系统,增加了部署和运维复杂性;二、分布式文件系统本身就是存储系统,因为用户权限引入其他存储系统,这个做法会非常奇怪,逻辑上经不起推敲。

FastCFS不依赖第三方存储系统,把用户及权限数据保存到服务组件FastDIR中。为了更优雅灵活地支持这一点,FastDIR在3月中旬支持了文件扩展属性(x-attribute)。

FastCFS的访问权限控制采用基于session的分布式访问控制。session由Auth server生成并分发给FastCFS的两大服务组件FastDIR server和FastStore server,从而实现了session本地验证。FastCFS的用户权限体系采用集中管理,分布式验证的做法,做到了极致性能。

另外一个特性分享给大家,FastCFS的用户权限及配额修改后,准实时(1秒内)生效;管理员可以自定义用户配额控制(防止用超)的时间精度,默认为10秒。




六、binlog机制简介

FastCFS采用经典的Master/Slave结构及数据同步复制的做法。如果slave在线,master同步调用slave;否则slave将进入数据恢复阶段,追上master的最新进度后,slave切换为在线状态,此后master将数据同步复制到slave。

FastCFS采用binlog记录数据更改操作,binlog中不会记录变更(如写入)的文件内容,binlog相当于是数据索引,非常简洁。

FastCFS中binlog的两大用途:①实现数据索引持久化存储,程序启动时通过重放binlog加载数据索引;②slave数据恢复时从master拉取缺失的binlog,然后基于该binlog进行数据恢复。大家直观感受一下如下所示的binlog片段:

第一列为更改时间(unix时间戳),第二列为数据版本号。多个数据副本的分布式系统要保证数据强一致性,就必须保证更改操作的顺序。采用单调递增的数据版本号,是严格保证更改顺序的有效方法。

FastCFS支持master失效时自动切换(failover),极端情况下发生master切换后,可能会导致原master和新master上的binlog部分数据不一致,而不一致的binlog数据只会在binlog文件的尾部,我们只需对最后N条(如3条)binlog进行校验即可。如果slave最后N条binlog和master对账失败,slave会退出运行,需要人工修复binlog(通常只需删除最后一条binlog)后该slave方可正常启动。

FastStore模块有两套binlog:用于slave数据恢复的replica binlog和用作数据索引的slice binlog。对于一次更新操作,先写slice binlog,然后写replica binlog。一次更新操作对应两次binlog写入,如何保证两次写入的事务性呢?FastCFS不允许写binlog失败,只有程序异常终止时(比如掉电、程序挂掉),二者才有可能不一致。因此写入binlog时不做校验,程序启动时对两个binlog进行对账,去掉尾部多余的binlog记录即可。

FastCFS中master同步调用slave完成后才写binlog,为什么不选择在调用slave前写binlog呢?master写入binlog的时机是有讲究的,这个问题就留给大家了。

最后总结一下,FastCFS中binlog是保证数据一致性的重要机制,binlog自身做到一致性非常关键,FastCFS采用的是binlog对账机制。




七、最新版本

截止目前(2021年6月23日)最新版本为v2.2.0

FastCFS V2.2.0 主要改进如下:

1. [fstore] 使用libaio实现异步读,随机读性能提升明显;

2. [fstore] 支持预读机制,顺序读性能提升显著;

3. 修复了3个bug:

  • [fstore] 修复V2.1.0引入的bug:第一次运行时,一个关键bool变量没有正确赋值;
  • [fuseclient] 修复列举目录导致元数据缓存的一致性问题;
  • [fauth] 修复username和poolname格式修饰符不当导致的乱码问题。

另,sungness 开发的集群运维工具(fcfs.sh) 和 vazmin 开发的k8s驱动(fastcfs-csi)已同步发布,欢迎大家测试和使用(FastCFS项目主页有链接)。

FastCFS V2.2.0采用异步读取和预读机制,读性能显著提升,至此FastCFS的IOPS全面超越Ceph:顺序写是Ceph的6.x倍,顺序读是Ceph的2.x倍,随机写大约是Ceph的2倍。详细的测试数据参见FastCFS项目官网:https://gitee.com/fastdfs100/FastCFS




版权声明:本文为CSDN博主「happy_fish100」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

参考原文:

https://blog.csdn.net/happy_fish100/article/details/117605651

https://blog.csdn.net/happy_fish100/article/details/117855493

https://blog.csdn.net/happy_fish100/article/details/117855540

https://blog.csdn.net/happy_fish100/article/details/117855576

https://blog.csdn.net/happy_fish100/article/details/117855626

https://blog.csdn.net/happy_fish100/article/details/117855693

https://blog.csdn.net/happy_fish100/article/details/118100942

https://blog.csdn.net/happy_fish100/article/details/118100942

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表