|
4.3 Facebook Haystack5 }* j$ _: S3 P
Facebook目前存储了2600亿张照片,总大小为20PB,通过计算可以得出每张照# c- I) K6 f' g# F
片的平均大小为20PB/260GB,约为80KB。用户每周新增照片数为10亿(总大小为' X- b( s4 D" u6 a9 b5 c; j
60TB),平均每秒新增的照片数为10 9 /7/40000(按每天40000s计),约为每秒3500
$ I- _- I8 c/ u次写操作,读操作峰值可以达到每秒百万次。
2 |2 D+ q: w! \( e$ r% b/ ~/ ~Facebook相册后端早期采用基于NAS的存储,通过NFS挂载NAS中的照片文件来! y" ^. q$ q. F* d g
提供服务。后来出于性能和成本考虑,自主研发了Facebook Haystack存储相册数据。- ]9 y k' H: \
4.3.1 系统架构4 C. q! `" R/ ~8 q+ |( z( g' c/ F
Facebook Haystack的思路与TFS类似,也是多个逻辑文件共享一个物理文件。6 ^8 M# I5 G9 w
Haystack架构及读请求处理流程如图4-6所示。+ F# K/ i7 H' v, N
图 4-6 Haystack架构图3 F/ f( c* F* h( G* \3 O9 ^
Haystack系统主要包括三个部分:目录(Directory)、存储(Store)以及缓存
0 O6 z3 `& i9 Q- o(Cache)。Haystack存储是物理存储节点,以物理卷轴(physical volume)的形式组. i' X: c* u$ E% O r q
织存储空间,每个物理卷轴一般都很大,比如100GB,这样10TB的数据也只需100个( v2 P5 z! ~6 l/ R2 K2 K
物理卷轴。每个物理卷轴对应一个物理文件,因此,每个存储节点上的物理文件元% i1 E0 _( O! R5 Q4 u
数据都很小。多个物理存储节点上的物理卷轴组成一个逻辑卷轴(logical9 E; m4 k$ x1 u- d
volume),用于备份。Haystack目录存放逻辑卷轴和物理卷轴的对应关系,以及照片( Q( ?' A, v# W, ?
id到逻辑卷轴之间的映射关系。Haystack缓存主要用于解决对CDN提供商过于依赖的0 j* S* e: z5 s. c& u
问题,提供最近增加的照片的缓存服务。
' T0 W8 f! l5 }5 \Haystack照片读取请求大致流程为:用户访问一个页面时,Web服务器请求& [# C' d* [ k) l
Haystack目录构造一个URL:http://<CDN>/<Cache>/<Machine id>/<Logical
# H0 ?7 Y4 {) l( G! ?volume,Photo>,后续根据各个部分的信息依次访问CDN、Haystack缓存和后端的. n6 ?' m8 j. }+ R+ M
Haystack存储节点。Haystack目录构造URL时可以省略<CDN>部分从而使得用户直
6 q7 z- s- T8 @: b) J9 J接请求Haystack缓存而不必经过CDN。Haystack缓存收到的请求包含两个部分:用户
" L4 K1 C; s, e) Q& D4 a4 ~, p浏览器的请求及CDN的请求,Haystack缓存只缓存用户浏览器发送的请求且要求请求
7 c. [9 v5 l. b9 g的Haystack存储节点是可写的。一般来说,Haystack后端的存储节点写一段时间以后8 }) y) f+ P8 R+ w- q
达到容量上限变为只读,因此,可写节点的照片为最近增加的照片,是热点数据。3 \) f9 V8 v' x
本节暂不讨论CDN,只讨论Haystack后端存储系统,包括Haystack目录和Haystack缓
+ \7 G: s* x0 G! T3 T* U$ z存两个部分。
( }$ Z1 h8 L" | ~- |5 v1.写流程0 R- ~6 z' \3 P! b6 F
如图4-7所示,Haystack的写请求(照片上传)处理流程为:Web服务器首先请求# A# n$ W+ {) n! \( |
Haystack目录获取可写的逻辑卷轴,接着生成照片唯一id并将数据写入每一个对应的
$ s. q8 |( K# D, f0 V9 J物理卷轴(备份数一般为3)。写操作成功要求所有的物理卷轴都成功,如果中间出
- O/ A8 e6 d7 v) ?' x现故障,需要重试。
4 J2 @: }1 d/ p9 X3 A图 4-7 Haystack写流程
$ e$ a/ ^" Q1 t) OHaystack的一致性模型保证只要写操作成功,逻辑卷轴对应的所有物理卷轴都存
- n- U! n6 @$ M& w1 y% a在一个有效的照片文件,但有效照片文件在不同物理卷轴中的偏移(offset)可能不# \! J. x) P( f, y Q/ Q% k- `
同。
' p4 f; U# e/ J' @, q" RHaystack存储节点只支持追加操作,如果需要更新一张照片,可以新增一张编号
% u" w( V7 o$ m) [6 [1 C& @相同的照片到系统中,如果新增照片和原有的照片在不同的逻辑卷轴,Haystack目录
. m% D M" d/ a1 k9 Z( ~的元数据会更新为最新的逻辑卷轴;如果新增照片和原有的照片在相同的逻辑卷
q5 C# j0 z# r0 B! L& y轴,Haystack存储会以偏移更大的照片文件为准。
# y, q7 G; b1 n7 @! n2.容错处理0 q7 e8 P1 b" d1 `* k, z. b) l
(1)Haystack存储节点容错
0 w- _0 Z4 a4 V% E1 b检测到存储节点故障时,所有物理卷轴对应的逻辑卷轴都被标记为只读。存储
' p& h7 {% B# Z1 p$ W节点上的未完成的写操作全部失败,写操作将重试;如果发生故障的存储节点不可
$ v' l5 E9 D; h. W0 m4 J+ V+ o; H恢复,需要执行一个拷贝任务,从其他副本所在的存储节点拷贝丢失的物理卷轴的
& a: Y# `4 Q5 r& W$ k数据;由于物理卷轴一般很大,比如100GB,所以拷贝的过程会很长,一般为小时, B1 U8 d( f( w3 _: }' ~0 o ^5 L! @
级别。. `0 o9 c0 z& E: c: s& q8 y1 u
(2)Haystack目录容错
9 w( [* [8 h5 ]7 U. ]Haystack目录采用主备数据库(Replicated Database)做持久化存储,由主备数据( m: _3 {4 G, }+ q0 ^- d( x
库提供容错机制。
( R# W! R- Z# ]! X3.Haystack目录" Q- S8 K5 R9 |: E& l
Haystack目录的功能如下:: l8 S1 m7 n; I6 `
1)提供逻辑卷轴到物理卷轴的映射,维护照片id到逻辑卷轴的映射;4 ]/ n2 k" _ x& \
2)提供负载均衡,为写操作选择逻辑卷轴,读操作选择物理卷轴;
" p. f& B7 E9 a# T3)屏蔽CDN服务,可以选择某些图片请求直接走Haystack缓存;& Y) ^3 A) B! v- L* p( H1 b3 y
4)标记某些逻辑卷轴为只读。
8 S' K. D l" Z) P, P) A根据前面的计算结果可知,Facebook相册系统每秒的写操作大约为3500次,每: \& F- Z( ^ s( t* K0 P" i
秒的读请求大约为100万次。每个写请求都需要通过Haystack缓存获取可写的卷轴,2 P! w3 ~! q1 v2 w$ D
每个读请求需要通过Haystack缓存构造读取URL。这里需要注意,照片id到逻辑卷轴
/ ^' f% Q- o! {% D+ C! A' }的映射的数据量太大,单机内存无法存放,笔者猜测内部使用了MySQL Sharding集: P3 T! z& g' X2 }0 ~3 ^, h
群,另外,还增加了一个Memcache集群满足查询需求。. t6 e# X @" B$ l6 {; h$ {
4.Haystack存储3 t O O/ V3 M8 P; _
Haystack存储保存物理卷轴,每个物理卷轴对应文件系统中的一个物理文件,每! o# y, x3 L8 q* n0 P! e7 H
个物理文件的格式如图4-8所示。
4 b) v1 h# J* s6 y图 4-8 Haystack数据块格式7 w% {3 w! ?# k. i& `
多个照片文件存放在一个物理卷轴中,每个照片文件是一个Needle,包含实际1 m1 F5 G5 S0 }7 \3 Q$ h
数据及逻辑照片文件的元数据。部分元数据需要装载到内存中用于照片查找,包括 } x0 D" m8 i5 x6 t
Key(照片id,8字节),Alternate Key(照片规格,包括Thumbnail、Small、Medium
% {* x9 z: P& i及Large,4字节),照片在物理卷轴的偏移Offset(4字节),照片的大小Size(4字+ T! k/ ^* B6 c1 O/ F7 J, o
节),每张照片占用8+8+4=20字节的空间,假设每台机器的可用磁盘为8TB,照片
) W4 ^) O+ n7 r- D平均大小为80KB,单机存储的照片数为8TB/80KB=100MB,占用内存/ \0 q# z6 {8 ]* X
100MB×20=2GB。
6 P3 L5 B( c/ X9 B; i( `3 q存储节点宕机时,需要恢复内存中的逻辑照片查找表,扫描整个物理卷轴耗时
* J5 e+ C* r$ ~$ _+ r5 w太长,因此,对每个物理卷轴维护了一个索引文件(Index File),保存每个Needle. @! M v' M/ f4 {6 i, n
查找相关的元数据。写操作首先更新物理卷轴文件,然后异步更新索引文件。由于
- l$ L* c" j0 W更新索引文件是异步的,所以可能出现索引文件和物理卷轴文件不一致的情况,不, o x* v0 ~# t
过由于对物理卷轴文件和索引文件的操作都是追加操作,只需要扫描物理卷轴文件5 I5 ^' X2 X: z i
最后写入的几个Needle,然后补全索引文件即可。这种技术在仅支持追加的文件系
' Z( a. t. A' q' p2 r2 V* j9 D统很常见。1 v0 B9 T# c: B3 X( J
Haystack Store存储节点采用延迟删除的回收策略,删除照片只是向卷轴中追加; V s" i1 ~$ R
一个带有删除标记的Needle,定时执行Compaction任务回收已删除空间。所谓8 N: ]/ [% x4 s1 B" |2 c- F0 g4 D
Compaction操作,即将所有老数据文件中的数据扫描一遍,以保留最新一个照片的原# u2 L: H* p* c
则进行删除,并生成新的数据文件。) P: K2 l; h* O0 n i% r+ n
4.3.2 讨论, j/ J& F8 g6 V8 Z* V1 j1 K
相比TFS,Haystack的一大特色就是磁盘空间回收。Blob文件在TFS中通过<Block
' b; l1 X: x1 q# D' [: j% q7 `id,Block offset>标识,因此,不能对TFS中的数据块进行重整操作;而Haystack中的
, i1 p4 ]6 f& g8 E3 Z0 L+ ^! w元信息只能定位到Blob文件所在的逻辑卷轴,Haystack存储节点可以根据情况对物理
2 c- j0 W' C' ]+ l( J; G/ A! i卷轴进行Compaction操作以回收磁盘空间。
3 X% B* W h o/ x# } uFacebook Haystack中每个逻辑卷轴的大小为100GB,这样减少了元信息,但是增0 W% M" U6 y/ z8 o$ S0 R9 Z
加了迁移的时间。假设限制内部网络带宽为20MB/s,那么迁移100GB的数据需要的
, ^5 h8 ]2 @! { ^时间为100GB/20MB/s=5000s,大约是一个半小时。而TFS设计的数据规模相比 f& P/ }7 o! k4 G5 i2 w- t* ?
Haystack要小,因此,可以选择64MB的块大小,有利于负载均衡。! I9 ?. ?6 c9 U" i# \& X, h2 x, K' q7 `
另外,Haystack使用RAID 6,并且底层文件系统使用性能更好的XFS,淘宝TFS2 P) Z1 t3 H6 z
不使用RAID机制,文件系统使用Ext3,由应用程序负责管理多个磁盘。Haystack使用; l% U* v9 h. Z0 ~ D
了Akamai&Limelight的CDN服务,而淘宝已经使用自建的CDN,当然,Facebook也在
( J6 g4 L! N. V7 E# S考虑自建CDN。. z! a# J- w$ N
! f0 j, q% ^% d; C( O2 o, F$ {8 ^& s0 k6 E& j) E: p- m& |
|
|