我跟存储的这10年

2017-09-18 09:38:24

我和存储的故事要从 10 年前在豆瓣的工作开始。 2007 年的 8 月,那会豆瓣还只有 4 台机器,支撑每日三百多万的  PV ,存储也用的是单机的本地存储,条目的照片按照类别放在一个目录里,一百多万的小文件,即使用了对小文件支持很好的  reiserfs ,也已经没办法用 ls 或者 rsync 来访问或者备份了。 Web  服务器是  Lighttpd ,配置了合适的缓存策略,在没有任何 CDN 缓存的情况下勉强能撑。但很危险,如果那块硬盘挂了的话,很多条目图片就没了。后来我们将目录结构调整成两级,第二级最多 10000 个文件,这样就实现了正常访问和备份。

一年后,豆瓣搬到了兆维工业园,服务器也更多了。我们发现服务器上的硬盘空间使用很不均衡,机器间的相互备份也很麻烦,想找一个分布式的存储方案来把所有硬盘空间统一成全局的存储系统。先尝试了 GlusterFS ,它优雅的设计以及跟单机文件系统的兼容性很吸引人,可以把单机的文件系统原封不动地加入到 GlusterFS 中提供对外访问。可惜那会的 GlusterFS  还不够成熟,弄不好就死机了,好在不会丢数据,得益于前面说的那个兼容性。后来有幸发现了 MooseFS (简称 MFS ),上手非常容易,也很稳定。当时也在调研 Hadoop 和 HDFS ,但 MooseFS 的 POSIX API 使得它更容易使用也能支撑更多的应用场景,就被大范围使用了,从一开始的数据备份,到跨机器数据共享,再到后来的大数据分析,基本上都是用它。最大的 MFS 集群是挂载在 /mfs,  由于使用太频繁,导致很长一段时间两只手都会下意识的输入  mfs 。

为了能够掌控 MFS ,我在调研时就开始通过阅读它的源代码来了解运作机制,结合之前已经学习过多次的 Google  的那篇 GFS 论文,对分布式文件系统怎么运作算是有了比较清楚的认识,当使用 MFS 碰到问题时,就自己打补丁来解决,并同时提交给上游,不少被官方接受(接受代码或者他们自己重新实现一下)。我们从一开始的 1.5 ,一直跟着官方升级,并维护少量自己的补丁,在 Gentoo 上维护补丁也挺愉快的。绝大部分时候都表现很好,时常光顾它的 WebUI 也是我喜欢干的一件事。几年下来也碰到过一两次事故,其中一次是在做故障切换时操作不当,导致 mfsmaster 启动时使用了初始化状态,文件系统是空的, chunk server 连接上 mfsmaster 并汇报自己拥有的数据块,被 mfsmaster 认为那些块不应该存在,就命令 chunk server 把它们删掉。还好发现得及时,只被删了少部分数据,也都是我们收集的内部日志数据,而不是更重要的用户数据。事后给 MFS 打了补丁,延缓删除这种未知数据块。

2008  年豆瓣开始往社区方向发展,做了用户相册,这对在线存储提出了更高的要求。我们当时调研了 MogileFS ,经过一段时间的使用之后感觉性能不太好,一方面是 MySQL 容易成为瓶颈,小文件直接放本地文件系统上的性能也不好,数据迁移很慢。那会 Amazon 的 Dynamo  论文流传很广,简化的 KV 系统以及最终一致性给存储系统的实现打开了另一扇门。当时还没有成熟的开源系统可以用,我们就自己开始做 Beansdb ,经过了几次迭代,从一开始基于文件系统的 Merkle 树,到 TokyoDB ,再到 Bitcask,慢慢稳定和成熟,支撑了上百个节点和接近 PB 的数据量。过去两年豆瓣的同学们又对 Beansdb 做了大的升级,目前还没有开源,具体细节我就不知道了。

2009 年之后,豆瓣的存储架构算是比较稳定和成熟了, MFS 和 Beansdb 承载了豆瓣的绝大部分数据。 MFS 负责离线部分,用来管理几乎所有机器的剩余磁盘空间,存放各种日志、备份,甚至开发的代码以及相关的各种数据。 MFS 的 POSIX API 给工程师带来了很大便利,包括后来能够快速开发 DPark 并投入生产环境使用也是受益于 MFS 的 POSIX API 。 Beansdb 则负责了在线系统的绝大部分数据(图片和长文本等),结构化数据仍然是 MySQL ,一开始设想的用 KV 系统取代 MySQL 因为最终一致性带来的诸多问题未能实现。我有幸参与了这两套系统的很多工作,也对 POSIX API 的便利性和最终一致性系统的局限性有了很深的体会。

在 2013 年离开豆瓣前夕,我尝试改进 MFS 以满足豆瓣日益增长的性能和可用性需求。一方面是把它的网络层从 poll 改成 epoll ,大大降低 mfsmaster 的 CPU 占用,以支撑上千的节点;同时也尝试把部分元数据缓存到客户端来降低 mfsmaster 的请求数,提升可扩展能力;实现多 master (镜像)来解决它的单点问题。那段时间很开心地写了很多 C 代码,而且能很快看到改动上线后大大地提升系统性能,就更开心了。可惜因为时间关系,离职前未能把这三部分做到更完善,豆瓣在使用了一段时间后遇到了一些问题,不想继续维护这个分支,就又切换到官方版本上去了。这些改进都发布在 github 上,尤其是双 master 镜像方案,给 MFS 社区不少启发,官方把大部分重新实现了一下,在闭源的 Pro 版本里面实现了 HA ,另一个开源分支 LizardFS 也是实现了类似的机制(然后号称有 HA 支持)。用 epoll 和客户端缓存来提升 master 的支撑能力, MFS 和 LizardFS 到现在都没有实现,很可惜。

2013 年秋天我到了 Facebook ,因为前几个月在 MFS 上的愉快经历,想继续做做分布式存储方面的事,就在 Bootcamp 后进入了 HDFS 组,希望能够继续探索分布式文件系统领域,给广大 FB 工程师更好的存储体验。当时 FB 除了大范围使用 HDFS  (百 PB 级别),也是使用了其他 POSIX 文件系统的,一个是购买的商业 NAS 存储 (PB  级别),另外一个是 GlusterFS 。这两个都有扩展能力问题, GlusterFS 尤其在元数据方面性能比较差,记得 ls 一个很大的备份目录需要几分钟!基于已有的经验判断,应该能够做出一个类似于 HDFS 的架构,能够支撑 10PB 以上的 POSIX 文件系统,作为那个 NAS 和 GlusterFS 的更好替代,甚至部分取代 HDFS 。可惜当时作为一个初来乍到的中国工程师(英语还说不流利),要想推进这样一个重量级的项目实在是困难重重。虽然我在技术实现上已经有很大进展,并在寻求早期内部客户的过程中,还是没有得到上级的支持,只好作罢,转头继续改进 HDFS 了。另外,也参与了另一个更大规模的存储系统的早期设计,因为 FB 还没对外说它,暂时就不公开讨论了。

因为更喜欢小公司的做事方式, 2014 年到了 Databricks ,做另一个我也非常喜欢的领域:分布式计算框架, Apache Spark 。因为之前在豆瓣做过 DPark ,到  Databricks  工作算是兴趣和经验的很好匹配。 Databricks  是围绕  Apache Spark 做一个云服务,让工程师或者数据分析人员能够很容易地使用 Apache Spark 做大数据分析。整个服务都部署在 AWS ,因为免于运维和低成本等多种因素, Databricks 选择 S3 为存储方案。 Spark 依赖于 HDFS 的 API ,而 S3 只是一个最终一致性的 KV 存储系统,只好在客户端把 S3 模拟成文件系统,勉强能用,但是有好多问题。我们花了很多精力去绕过那些问题,最新的 DBIO 有了不少突破。 AWS 的 S3 团队也无法给出解决那些问题的时间表,因为很多问题是由系统设计造成的,考虑到现有系统的兼容性等诸多因素,很可能永远解决不了。

S3 的优点已经被广泛认识(可扩展,低成本,免运维),简单列一下 S3 的几个问题: 1) S3  缺乏真的目录结构和原子改名,相当于一个不可以改表结构的数据库,导致 Spark 不能保证计算结果的正确和稳定提交; 2)  文件不方便修改,会导致产生大量小文件,之后访问会很慢  3) S3  的元数据访问很慢并且很贵,我们 S3 的成本一半是遍历文件列表产生的   4 )不正确的元数据缓存导致应用经常被告知该存在的文件不存在,导致应用在随机的地方 crash 。另外, Databricks 又在 S3 的 Java SDK 之上做了一个简单封装 DBFS ,导致 Python 和 R 用户访问数据更不方便。我给内部的封装做了一个挺挫的 FUSE 接口( Python 实现的)给客户用,虽然性能很差,用的人还蛮多。

过去几年中在离线应用中被 S3 坑过太多次,   一直在思考有什么更好地替代方案。 AWS 在  2016  年正式推出了 EFS ,可惜定价太高实在不适合大数据应用。自己维护 HDFS 或者 MFS 也是个大挑战,连 Databricks 也不想趟这浑水,而且运行成本也很高,据 Airbnb 测算, HDFS 的成本是 S3 的 15 倍,但因为 S3 的诸多问题他们仍然是大量使用 HDFS 。

鉴于现有解决方案都不理想,也在思考能不能做一个方案来解决这些问题,尤其是在公有云这个场景中,并尝试做一些原型来验证想法。像 S3 这样的对象存储几乎成了公有云的标配,因为 API 简单且一致性要求低,很容易做到大规模可扩展和低成本。但它欠缺的是好用的 API 和一致性保证,或许可以基于它实现一个 POSIX 文件系统。去年有了实质性的进展,并找了几个公司做内测,效果还不错。

今年 6 月从 Databricks 离职,在华创和清源等投资人的帮助下创立了 Juicedata ,致力于帮企业客户解决数据访问和管理问题。我们做的 JuiceFShttps://juicefs.io/) 是一个基于公有云对象存储的 POSIX 文件系统,能够跟 S3 一样按需伸缩和低成本,没有维护的烦恼,还跟 MFS 一样方便使用。目前在公测阶段, 10 月份会开始正式商用。欢迎有兴趣的同学试用,或者一起探讨存储方面的问题和技术等。 Juicedata  才刚刚开始,我们会努力提供最好的存储解决方案,也欢迎志同道合的同学们加入。