AirJD 焦点
AirJD

没有录音文件
00:00/00:00
加收藏

分布式存储的元数据设计 by 李道兵@七牛

发布者 store
发布于 1438047926310  浏览 6893 关键词 NoSQL, DevOps, 数据库 
分享到

第1页

分布式存储的元数据设计

李道兵 <lidaobing@gmail.com> 七⽜牛云存储 2015-04 北京



第2页

引⼦子

• ⾯面试新⼈人时最经常被问到的⼀一句话:七⽜牛的云存储真 的是⾃自⼰己写的么,是不是基于 Hadoop 的?



第3页

Outline

• ⽆无中⼼心的存储设计: glusterfs • 有中⼼心的存储设计:hadoop • 基于数据库的存储设计: gridfs, hbase • 绕过问题的存储设计: fastdfs



第4页

glusterfs

• 设计⺫⽬目标

• 兼容 POSIX ⽂文件系统: 你的应⽤用程序⽆无需修改就可以 放到 glusterfs 上来运⾏行

• ⽆无中⼼心节点: 性能瓶颈没有了,单点故障也没有了

• 扩展能⼒力: ⼤大容量存储都需要这个

• 我们在这⾥里不讨论 POSIX 兼容的优劣,集中通过 glusterfs 来讨论⽆无中⼼心节点设计中普遍遇到的⼀一些难点



第5页

glusterfs

• glusterfs 是⼀一系列⽆无中⼼心存储的设计的代表

• ⽆无中⼼心暗⽰示着我们可以通过内容的 key 推算出来这个 key 的存储位置

• 在绝⼤大部分实践中,在这种设计下如果出现单盘故障,处理模式如下

• 去掉坏盘,换上新盘

• 从⽼老盘拷⻉贝数据到新盘

• 这个模式最⼤大的问题是修复时间,4T盘在 100MB/s 的修复速度下需要 ⾄至少 11 个⼩小时,这么⻓长的修复时间会导致数据的可靠性降低(在这 11个⼩小时内另外两块盘的损坏概率)

• 另外⼀一种修复模式是在读的时候发现有坏块,然后触发修复,在这种模 式下修复只会更糟糕。



第6页

glusterfs

• 如何回避掉这个问题呢?

• 引⼊入中间层记录分区和物理设备的关系,这样磁盘 损坏不⽤用等换盘就可以开始修复

• ⼀一个磁盘分成多个区,每个区可以到不同的盘上去 修复,那么可以⼤大幅度缩短修复时间,⽐比如分到 50 个区(每个区 80GB), 那么修复时间就可以缩 ⼩小到 13分钟左右。



第7页

glusterfs

• 扩容 • 在⽆无中⼼心设计中,扩容往往伴随着数据的再平衡, 再平衡会带来如下的挑战 • ⺴⽹网络拥塞:可以使⽤用独⽴立的迁移⺴⽹网络来改善 • 迁移时间⻓长且迁移期间数据读写逻辑变得更复杂 :多加测试改善代码质量



第8页

glusterfs

• 不⽀支持异构存储

• ⽐比如⼩小⽂文件经常伴随着很⾼高的 iops 需求,针对⼩小⽂文件我们可 以引⼊入SAS或者SSD盘来得到更⾼高的 iops, 但对于⽆无中⼼心存储 来讲,这种⽅方法很难实施。

• 类似的异构需求还包括某些客户数据只想存两份,⽽而其他客 户数据则想多存⼏几份的情况,这些在⽆无中⼼心存储中都是很难 解决的。

• ⼩小⽂文件的问题针对读取的部分可以通过缓存层来改善,但对 于⾼高频率的写⼊入没有太好的解决⽅方案

• 这⼉儿也存在⼀一个基于 hash 碰撞的攻击⽅方案,不过影响不⼤大。



第9页

glusterfs

• 数据不⼀一致的问题

• ⽐比如我们要覆盖⼀一个 key,但在覆盖过程中出现意 外,导致只覆盖了三个副本中的两个或者⼀一个。这 个时候就很容易读到错误的数据。

• 在写⼊入⽂文件时,先写临时⽂文件,最后再重命名能改 善这个问题,但仍然不完美。



第10页

glusterfs

• 问题总结 • 坏盘修复问题:元数据+分区可以改善这个问题 • 扩容动作⼤大: 忍 • ⼩小⽂文件⾼高IOPS: 劣势,集群⾜足够⼤大的话可以靠规模 来抗住 • 数据不⼀一致的问题: 复杂度会变⾼高



第11页

Hadoop

• 设计⺫⽬目标 • ⼤大⽂文件 • offline 使⽤用 • 可伸缩

• 元数据(NameNode)设计 • 主备模式,各⼀一台机器 • 数据尽量加载到内存,提⾼高性能 • 放弃⾼高可⽤用,进⼀一步提⾼高元数据的性能 (NameNode 的变更不是同 步更新到从机,⽽而是通过定期合并的⽅方式来更新)



第12页

Hadoop 优点

• Hadoop 为⼤大⽂文件服务:

• 意味着 NameNode 不会太⼤大,⽐比如 64M 的块⼤大⼩小, 10PB ⽂文件只 需要存储 1.6亿条数据,如果每条数据 200B, 那么需要 32GB 左右 的内存。

• 元信息的 qps 也不⽤用太⾼高,如果每次 qps 能提供⼀一个⽂文件块的读 写,那么 1000qps 就能达到 512Gb/s 的读写速度,满⾜足绝⼤大部分 数据中⼼心的需求。

• Hadoop 为offline业务服务: ⾼高可⽤用可以部分牺牲

• Hadoop 为可伸缩服务: 伸缩的是存储节点,元信息节点⽆无需伸缩。



第13页

Hadoop 为什么不能当公有 云?

• 元信息容量太⼩小:1.6 亿条数据就占掉 32GB,100 亿的数据需要 2000GB 内存,这个完全没法接受

• 元信息节点⽆无法伸缩: 元信息限制在单台,1000qps 甚⾄至 15000qps 的单机容量远不能达到公有云的需 求。

• ⾼高可⽤用不完美: NameNode 问题



第14页

其他有中⼼心设计

• WRN算法 • 写⼊入了 W 份才算成功 • 读取时成功读取 R 份才算成功 • W + R > N (其中N 为总副本数)

图片来自:莫华枫的《云存储的⿊黑暗面:元数据保障》



第15页

WRN算法

• W,R,N 的选择 • ⽐比如2,2,3这种情况,写⼊入两份就算成功,但如果 其中⼀一台机器下线,这个数据就可能读不出来了 • 所以446 或者 669 这样的选择会更好。但机器越 多,响应会越差。



第16页

WRN算法

• 失败的写⼊入会污染数据

• ⽐比如 446 的场景,如果写⼊入只成功了3份,那么这 次写⼊入是失败的,但如果是覆盖写⼊入,那么也就意 味着现在有三份正确的数据,三份错误的数据,哪 ⼀一个是正确就⽆无从判别了。

• 写⼊入数据带版本(不覆盖,只是追加)能改善这个问 题,但带来了⼀一个攻击点:反复覆盖同⼀一个⽂文件, 导致数据库出现性能瓶颈



第17页

有元数据的存储

• Hadoop • NameNode 不是⾼高可⽤用 • NameNode 容量不⾜足

• WRN⽀支持的元数据 • 响应性差 • 有丢失数据可能性 (覆盖写) / 有攻击点 (带版本写)



第18页

基于数据库的分布式存 储⽅方案

• GridFS (基于 MongoDB) • HBase • HBase + Hadoop



第19页

GridFS

• 基于 MongoDB • 分块存储,每块⼤大⼩小为255KB • 数据直接放在两个表⾥里边

• chunks: 存储数据,加上元信息后单条记录在 256KB 以内

• files: 存储⽂文件元信息



第20页

GridFS 优点

• 两个需求(数据库和⽂文件都需要持久化),⼀一次满⾜足 • 拥有MongoDB的全部优点: 在线存储,⾼高可⽤用,可伸

缩(*),跨机房备份,… • ⽀支持 Range GET,删除时可以释放空间(需要⽤用

mongodb 的定期维护来释放空间)



第21页

GridFS 的缺点

• oplog 耗尽:

• oplog 是 mongodb 上⼀一个固定⼤大⼩小的表,⽤用于记录 mongodb 上的每 ⼀一步操作,MongoDB 的 ReplicaSet 的同步依赖于 oplog。

• ⼀一般情况下 oplog 在 5GB-50GB 附近,⾜足够⽀支撑 24 ⼩小时的数据库修 改操作。

• 但如果⽤用于 GridFS,⼏几个⼤大⽂文件的写⼊入就会导致 oplog 迅速耗尽,很 容易引发 secondary 机器没有跟上,需要⼿手⼯工修复,⽽而且MongoDB 的修复⾮非常费⼒力。

• 简单来说就是防冲击能⼒力差,这个跟数据库的设计思路有关。

• 除了前⾯面提到⼿手⼯工修复的问题外,冲击还会造成主从数据库差异拉⼤大, 对于读写分离,或者双写后再返回的场景带来不⼩小的挑战。



第22页

GridFS 的缺点

• 滥⽤用内存

• mongodb 使⽤用 mmap 来把磁盘⽂文件映射到内存, 对于 gridfs 来说,⼤大部分场景都是⽂文件只需读写⼀一 次,对于这种场景没法做优化,内存浪费巨⼤大,会 挤出那些需要正常使⽤用内存的数据。

• 设计阻抗失配带来的另外⼀一个问题。



第23页

GridFS 的缺点

• 伸缩性

• 需要伸缩性就必须引⼊入 mongodb sharding

• sharding 的情况下你需要使⽤用 files_id 作为 sharding key

• 如果你不修改程序的话files_id 是递增的,也就是说所有的写 ⼊入都会压⼊入同⼀一个集群,⽽而不是均匀分散。

• 在这种情况下你需要改写你的驱动,引⼊入⼀一个新的 files_id ⽣生成 ⽅方法。

• 另外,MongoDB Sharding在⾼高容量⾼高压⼒力下的运维很痛苦(⼤大 家可以参考百度⺴⽹网盘组之前的⼀一些 PPT)



第24页

GridFS

• 低压⼒力: 没问题,挺好⽤用的 • 中压⼒力: 如果单台机器能抗住你的存储,建议分离数

据库和GridFS, 使⽤用独⽴立的机器资源 • ⾼高压⼒力: 不建议使⽤用 GridFS



第25页

HBase

• 前⾯面提到 Hadoop 因为 NameNode 容量问题所以不 合适⽤用来做⼩小⽂文件存储,那么 HBase 是否合适呢?



第26页

HBase 的优点

• 伸缩性,⾼高可⽤用都在底层帮你解决了 • 容量很⼤大,⼏几乎没有上限。



第27页

HBase 缺点

• 微妙的可⽤用性问题

• ⾸首先是 Hadoop NameNode 的⾼高可⽤用问题

• HBase 的数据放在 Region 上,Region 会有分裂的问 题,在分裂和合并的过程中,这个 Region 会不可⽤用

• 我们可以采⽤用预分裂来回避这个问题,但这就要求 预 先知道整体规模,并且key 的分布是近均匀的

• 在多租户的场景下,key 均匀分布很难做到(除⾮非舍 弃掉 key 必须按顺序这个需求)



第28页

HBase 的缺点

• ⼤大⽂文件⽀支持 • 10MB以上的⼤大⽂文件⽀支持不好 • ⼀一个改良⽅方案是把数据拼装成⼤大⽂文件,然后 hbase 只存储⽂文件名,offset 和 size • 这个改良⽅方案其实挺实⽤用的,不过如果要做到空间 回收就需要补很多开发了。



第29页

HBase⽅方案

• HBase存元数据,Hadoop 存数据算⼀一个可⽤用⽅方案, 但是

• Hadoop是 offline 设计的,NameNode的⾼高可⽤用考 虑不充分

• HBase的 Region 分拆和合并会造成短暂的不可 ⽤用,如果可以的话最好做预拆,但预拆也有问题

• 如果对可⽤用性要求低的话问题不⼤大



第30页

绕过问题也是解决问题的⽅方 式: fastdfs

• fastdfs:

• hadoop的问题是NameNode 压⼒力过⾼高,那么 fastdfs 的思路就是给 NameNode 减压。

• 减压的⽅方法就是把 NameNode 的信息编码到key⾥里边

• 范例URL: group1/M00/00/00/rBAXr1AJGF_3rCZAAAAEc45MdM850_big.txt

• 也就是说 NameNode 只需做⼀一件事情,把 group1 翻译成具体的机器名字



第31页

fastdfs 的优点

• 结构简单,元数据节点压⼒力低 • 扩容简单,扩容后数据⽆无需重新平衡



第32页

fastdfs 缺点

• 不能⾃自定义 key: 这个对多租户是致命的打击,⾃自⼰己使⽤用也会减 低灵活性

• 修复速度:

• 磁盘镜像分布,修复速度取决于磁盘写⼊入速度,⽐比如 4TB 的 盘, 100MB/s 的写⼊入速度,那么需要⾄至少 11个⼩小时

• ⼤大⽂文件容易造成冲击

• ⾸首先是⽂文件⼤大⼩小有限制(不能超过磁盘⼤大⼩小)

• 其次是⼤大⽂文件没有分⽚片,导致⼤大⽂文件的读写都由单块盘来承 担,所以对磁盘的⺴⽹网络冲击很⼤大



第33页

⽆无中⼼心设计 有中⼼心设计



优点 ⽆无⾼高压⼒力节点 扩容,修复更灵活



缺点

修复慢,扩容难 ⽆无异构⽀支持 数据不⼀一致

中⼼心节点难设计



基于数据库的设计



简单,易上⼿手



设计失配 容量有限



fastdfs



中⼼心压⼒力⼩小,易扩容



key不能随便重命名 ⼤大⽂文件⽀支持差



第34页

Q&A



支持文件格式:*.pdf
上传最后阶段需要进行在线转换,可能需要1~2分钟,请耐心等待。