第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