前言

Facebook(后面简称fb)是世界最大的社交平台,需要存储的数据时刻都在不断剧增(占比最大为图片,每天存储约20亿张,大概是微信的三倍)。

那么问题来了,fb是如何存储兆级别的图片?并且又是如何处理每秒百万级别的图片查询?

本文以简单易懂,图文并茂的方式来解释其中的原理,并不涉及空洞,难解的框架,也没有大篇章的废话铺陈,只有痛点与反思;就如同fb的架构师所说:fb的存储架构就像高速公路上换轮胎,没有最完美的设计,我们最求的只是如何让它变得更简单。

短篇介绍

fb的图片存储系统叫做HayStack,目前已存储超过120PB的数据,用户每天会上传20亿张图片。fb图片搜索峰值,需要提供每秒100-200万张的图片搜索。这些数据还再不断地增加。

稍微分析下用户使用场景,图片写入一次,频繁读取,从不修改,很少删除。传统的文件系统:每个图片都会有一些元数据,在我们的需求中,这些信息无用,且浪费存储空间,更大的性能消耗是文件的元数据需要从磁盘读到内存中来定位图片位置,在fb的量级上,元数据的吞吐量便是一个巨大的瓶颈。

高吞吐量,低延迟是HayStack所追求的,所以HayStack希望每个图片读取操作至多需要一个磁盘,并且减少每个图片的必要元数据,并将它们保存至内存中。为了做好容灾,HayStack会将图片复制多张并保存至不通数据中心,以确保不反回404,error给客户。

典型的设计方案

上图为典型的设计方案:

1.用户通过浏览器发送图片信息请求至web server;2.web server 构造一个url,引导浏览器到对应位置下载图片;3.通常这个url指向一个CDN,如果CDN有缓存相关图片的话,它会将图片立刻返回给浏览器;4.否则,会解析url,并在Photo Storage中找到对应的图片;5.6.返回给用户。

NAS-NFS

在fb的服务中,只有CDN不足以解决全部需求,对于新图片,热门图片CDN确实很高效。但是对于一些个人上传的老图片请求,CDN基本上会全部命中失败,又没有办法将图片全部缓存起来。所以这里,可以采用NAS-NFS来解决问题。

基本操作与上面相同,5.6.photo store server 解析url得出完整的卷和路径信息,在NFS上读取数据,然后返回给CDN。

这种设计的瓶颈:NFS卷的每个目录下存储上千张图片,导致读取时产生了过多的磁盘操作。

HayStack

HayStack架构包含3个核心组件:HayStack Store,HayStack Directory和HayStack Cache。 Store是存储系统,负责管理图片的元数据。不同机器上的物理卷对应一个逻辑卷,HayStack将一个图片保存至一个逻辑卷时,那么图片便对应写入所有物理卷。Directory 维护了逻辑到物理卷的映射以及相应的元数据,例如说,某张图片保存在哪个物理卷里,某个物理卷的存储空间等。Cache的功能,类似内部的CDN,它帮Store挡住热门搜索。

上图描述了3个核心组件的相互作用。在HayStack架构中,浏览器的请求被引导至CDN中(或Cache上),Cache本质就是CDN,为了避免冲突,我们使用CDN来表示外部系统,使用Cache表示内部系统。

1.当用户发出请求给web server,2.web server 使用Directory来构建图片的url,3.4.5.6.7.8.9.10.url包含一段信息,如下:

http(s)://CDN/Cache/machine_id/volume_ID_Photo

一目了然,url包含CDN地址信息,Cache信息,以及保存图片的物理卷ID,以及图片信息。

图4,位用户上传图片的流程,1.用户发送请求至web server;2.web server请求Directory一个可用的逻辑卷,物理卷,并将图片信息记录下;3.将相关信息发送至web server;4.web server将图片上传至Store;5.返回成功信息。

Directory

主要有4个功能:

1.它提供了逻辑卷到物理卷的映射,web服务器上传或读取图片时需要使用这个映射。

2.它在分配写请求,读请求到物理卷时,需保证负载均衡。

3.它决定一个图片的请求,是发送至CDN或Cache,这个决定可以动态调整是否依赖CDN。

4.它指定哪些卷是只读的。

当我们增加Store的时候,那些卷都是可写的,可写的机器会收到上传信息。当它们到达容量上限时,标记它们为只读。

Cache

Cache的实现可以理解为一个分布式Hash Table,以图片ID为key,定位缓存的图片数据。如果Cache未命中,那么Cache则根据URL到指定的Store中,读取图片数据。

Store

很简单,根据提供的一些元数据信息,包括图片ID,逻辑卷ID,物理卷ID,找到对应的图片,未找到则返回错误信息。

下面简单描述一下物理卷与映射的结构,一个物理卷可以理解为一个大型文件,包含一系列的needle,每个needle就是一张图片。如下图所示。

为了快速索引needle,Store需要为每个卷提供一个内存中的key-value映射。

HayStack文件系统

HayStack可以理解成基于Unix文件系统搭建的对象存储架构。Store使用的文件系统是XFS,XFS有两个优点,首先,XFS中的临近大型文件的blockmap很小,可放入内存存储。再者,XFS提供高效的文件预分配,减少磁盘碎片问题。使用XFS,可以完全避免检索文件系统导致的磁盘操作。

Facebook兆级别图片存储及每秒百万级别图片查询原理的更多相关文章

  1. 如何生成每秒百万级别的 HTTP 请求?

    第一篇:<如何生成每秒百万级别的 HTTP 请求?> 第二篇:<为最佳性能调优 Nginx> 第三篇:<用 LVS 搭建一个负载均衡集群> 本文是构建能够每秒处理 ...

  2. epoll的内部实现 & 百万级别句柄监听 & lt和et模式非常好的解释

    epoll是Linux高效网络的基础,比如event poll(例如nodejs),是使用libev,而libev的底层就是epoll(只不过不同的平台可能用epoll,可能用kqueue). epo ...

  3. 使用表类型(Table Type-SqlServer)实现百万级别的数据一次性毫秒级别插入

    使用表类型(Table Type)实现百万级别的数据一次性插入 思路 1 创建表类型(TaBleType)         2 创建添加存储过程         3 使用C#语言构建一个DataTab ...

  4. JAVA使用POI如何导出百万级别数据(转)

    https://blog.csdn.net/happyljw/article/details/52809244   用过POI的人都知道,在POI以前的版本中并不支持大数据量的处理,如果数据量过多还会 ...

  5. JAVA使用POI如何导出百万级别数据

    用过POI的人都知道,在POI以前的版本中并不支持大数据量的处理,如果数据量过多还会常报OOM错误,这时候调整JVM的配置参数也不是一个好对策(注:jdk在32位系统中支持的内存不能超过2个G,而在6 ...

  6. JAVA使用POI如何导出百万级别数据(转载)

    用过POI的人都知道,在POI以前的版本中并不支持大数据量的处理,如果数据量过多还会常报OOM错误,这时候调整JVM的配置参数也不是一个好对策(注:jdk在32位系统中支持的内存不能超过2个G,而在6 ...

  7. Excel如何快速渲染百万级别的数据

    Excel主要经历1.查询2.渲染的方式 关于查询: 不同技术水平的人有不同的解决方案,目前我采用的是 1:多线程查询 2:一个异步后台线程每次查询100条便渲染,采用的“懒加载方式”,这样可以做到实 ...

  8. 百万级别数据Excel导出优化

    前提 这篇文章不是标题党,下文会通过一个仿真例子分析如何优化百万级别数据Excel导出. 笔者负责维护的一个数据查询和数据导出服务是一个相对远古的单点应用,在上一次云迁移之后扩展为双节点部署,但是发现 ...

  9. oracle count 百万级 分页查询记要总数、总条数优化

    oracle count 百万级 分页查询记录总数.总条数优化 oracle count 百万级 查询记录总数.总条数优化 最近做一个项目时,做分页时,发现分页查询速度很慢,分页我做的是两次查询,一次 ...

随机推荐

  1. Duilib第一步(II)-Hello World

    My first Duilib program 1. Prepare for development 打开DuiFarm项目DuiFarm.cpp文件,将除_tWinMain函数之外所有内容删除.删除 ...

  2. Create小程序

    我有时候喜欢直接用命令行创建.编译.执行java文件, 每次创建一个文件都要新建一个.java文件,然后再编辑.java文件加入类名,主函数…… 这些流程我有点厌倦,于是就编写了一个超级简单的自动创建 ...

  3. Android 文字过长TextView如何自动截断并显示成省略号

    当用TextView来显示标题的时候,如果标题内容过长的话,我们不希望其换行显示,这时候我们需要其自动截断,超过的部分显示成省略号. 如下图所示,标题过长,自动换行了,显示不是很好看. 这时候我们需要 ...

  4. LeetCode第六天

    第六天 30.(219) Contains Duplicate II JAVA class Solution { public boolean containsNearbyDuplicate(int[ ...

  5. react+react-router+react-redux+nodejs+mongodb项目

    一个实际项目(OA系统)中的部分功能.这个demo中引入了数据库,数据库使用了mongodb.安装mongodb才能运行完整的功能.要看完整的项目可以移步我的github 技术栈 React v15. ...

  6. day4(while 、练习题)

    一.while ... else 方法 while else 的作用就是,确定循环正确执行完毕,else里面可以提示完成的情况. 二.练习题 1.编译型语言是编译完之后执行,解释性语言是边编译边执行, ...

  7. 为什么使用正则test( )第一次是 true,第二次是false?

    今天朋友问我一个问题,我现在需要多次匹配同一个内容,但是为什么我第一次匹配,直接是 true,而第二次匹配确实 false 呢? var s1 = "MRLP"; var s2 = ...

  8. iOS学习 NSString常用技巧

    字符串是程序设计最常用的数据类型之一了.在Mac/iPhone编程中,苹果为我们提供了一个不同的字符串类型NSString.有别与普通的String为数据类型,NSString其实是一个对象类型.NS ...

  9. 数据排序--vue

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. 第I篇PCI体系结构概述

    PCI总线作为处理器系统的局部总线,主要目的是为了连接外部设备,而不是作为处理器的系统总线连接Cache和主存储器.但是PCI总线.系统总线和处理器体系结构之间依然存在着紧密的联系. PCI总线作为系 ...