资讯详情

资讯详情

分布式存储核心机制与实战:从HDFS到对象存储

大数据分布式存储这几年一直是后端和大数据岗位的核心能力要求之一也是很多从单体开发转行到数据工程的人必须迈过去的一道坎。很多人一听到“分布式存储”就联想到复杂的集群、一堆论文里的协议、各种玄乎的概念实际上它没有那么神秘。把问题拆开看分布式存储要解决的始终是三件事数据放哪里、数据怎么找回来、机器坏了怎么办。把这三点吃透再看任何分布式存储系统都会轻松很多。这篇文章我会从工程实践的角度把分布式存储的底层逻辑、核心机制、主流选型、实战搭建以及生产环境最常见的坑一次说清楚。内容偏向Hadoop生态和对象存储方向适合正在学习分布式存储的开发者、准备往大数据方向转行的后端工程师也适合已经入行但想补一补存储底层原理的读者。1. 先搞清楚分布式存储到底解决什么问题1.1 从单机磁盘到分布式存储的必然路径先回忆一下我们最早是怎么存数据的。一台服务器插几块磁盘格式化一个文件系统数据往里写。这套方案在小数据量、低并发场景下完全够用但随着数据增长单机会遇到四个绕不过去的问题。第一是容量瓶颈。一块磁盘现在主流也就十几TB一台机器就算挂24块盘总容量也就几百TB听起来很大但一次日志采集、一份用户行为数据、几个月的监控指标轻松就能填满。第二是吞吐瓶颈。单机磁盘的写入速度是物理上限的千兆网卡千兆限制万兆网卡也会被磁盘顺序写的速度限制数据量到了一定规模单台机器扛不住并发写入。第三是扩展成本。单机扩展靠换更大的机器、加更多的盘这是垂直扩展很快会遇到成本和物理上限的双重压力。第四是单点故障。磁盘会坏服务器会宕机只要数据只存在于一台机器上这台机器挂了数据就没了。这四个问题决定了只要数据规模大到一定程度单机存储这条路必然走到头。也正因为这样分布式存储从诞生那天起就不是为了炫技而是为了在普通硬件上构建一个容量可扩展、吞吐可扩展、故障可恢复的存储底座。1.2 分布式存储不是“多台机器放数据”这么简单很多人对分布式存储的第一个误解是把数据分散到多台机器上存放不就是分布式存储了吗这个想法只对了一半。假如你把一个100GB的文件切成100份每台机器存1份这确实是“分布式存放”但离“分布式存储系统”还差得远。一个合格的分布式存储系统至少还要具备三个特征。第一统一的命名空间。用户看到的应该是一个完整的目录树或者一个完整的文件视图访问任意路径都能找到数据而不需要自己记住数据到底在哪台机器上。这就像你把钱存在多个银行网点但你只需要记住一张卡号而不是记住每个网点分别存了多少钱。第二水平扩展能力。加机器就能扩容量、扩吞吐数据能自动迁移到新机器上这是分布式存储最核心的价值。如果一个系统加机器还要手动搬数据、还要改访问路径那它不算真正的分布式存储。第三自动故障容错。某个节点宕机、某块磁盘损坏系统能在不中断服务、不丢数据的前提下自动恢复。这是分布式存储和普通文件备份的本质区别。理解了这三点你再看任何分布式存储产品——不管是HDFS、对象存储、还是各种分布式数据库——都会发现它们所有复杂的设计都是在围绕“统一视图、水平扩展、自动容错”这三个目标打转。2. 拆开看分布式存储的四大核心机制2.1 数据分片把大文件切成能管理的块数据分片是分布式存储的地基。一个文件不能一整块塞给一台机器必须切碎分散到多个节点上。分片的方式各有不同但核心思路就是三类。第一类按固定大小切片代表作是HDFS的Block。一个128MB的文件会被切成若干个128MB的块每个块独立存放、独立复制。第二类按范围切分代表作是HBase的Region、以及各种分布式关系型数据库。一张表按主键范围划分成多个区间各自落在不同的节点上。第三类按哈希切分代表作是Cassandra和各类缓存中间件通过哈希函数决定每条数据去哪个节点。这里有必要说一下HDFS为什么默认块大小是128MB。这个值不是拍脑袋定的它的核心逻辑是让“寻址时间”远小于“传输时间”。机械硬盘的寻址时间大约10ms左右传输速度大约100MB/s要让寻址开销占比降到1%以下传输时间至少要达到寻址时间的100倍也就是1秒对应传输的数据量大约就是128MB。块太小寻址开销占比太高吞吐上不去块太大map任务数过少并行度又不够。所以你去看HDFS的块大小调优本质上是在“寻址开销”和“并行粒度”之间找平衡。离线大扫描场景块设大一点通常更划算但小文件特别多的时候块设多大都救不了你那个问题在后面专门说。2.2 副本机制用冗余换可用性分布式存储不可能指望硬件永远不出故障。磁盘损坏、网络闪断、节点宕机都是常态而不是意外。所以几乎所有分布式存储系统都会用副本机制来换可用性。副本机制的核心是三个问题副本数设多少、副本放在哪里、读写走哪个副本。副本数一般默认3这个数字是“容错能力”和“写入成本”的折中。3副本可以容忍任意一个节点故障同时写入放大系数只有3倍相比5副本、9副本成本可控得多。如果你对可用性要求极高可以调大副本数如果你存的是冷数据、丢了也能从其他地方重建副本设2也能接受。副本放置策略也很讲究。以HDFS为例第一个副本放在客户端所在的节点上第二个副本放在同机架的另一个节点上第三个副本放在不同机架的某个节点上。这样设计的好处是同机架副本保证读写性能跨机架副本保证容错能力——一个机架整体断电、交换机挂了数据依然在其他机架有副本。读写路径同样要关注。写入数据时客户端先把数据发给第一个副本所在节点由它转发给第二个、第三个副本这串行管道能保证三个副本数据一致。读取数据时会优先读本地节点或本机架的副本减少跨机架网络开销。在这里有一个很多新手容易忽略的点副本不是越多越好。副本越多写入放大越严重磁盘空间消耗也越大。3副本看起来是3倍容量但实际上一块8TB的盘真正可用的存储空间只有大约2.6TB左右这个账一定要提前算清楚。2.3 元数据服务分布式存储的“大脑”数据分散到几千台机器之后最棘手的问题变成了客户端想读一个文件怎么知道这个文件有哪些块、这些块分别在哪些机器上这个答案就是元数据服务。它维护着“文件路径 → 块列表 → 块所在的节点列表”这张映射表是整个分布式存储系统的“索引本”和“大脑”。HDFS里这个角色叫NameNode对象存储里这个角色通常是Bucket索引和对象元数据数据库各种分布式数据库里的Region路由表也承担类似职责。元数据服务必须快因为每一次读写都要先查它元数据服务还必须是高可用的因为它挂了整个集群就不能对外提供服务了。元数据服务是整个分布式系统里最难做的部分。传统方案是一主一备主节点挂掉后由备节点接管HDFS的高可用就是这么做的。更现代的方案是直接把元数据做成一个分布式的KV存储比如很多对象存储的元数据都在一套独立的高性能KV集群上这样元数据自身也能水平扩展不依赖“一台超大内存的机器”。这个设计差异直接决定了系统的规模上限。HDFS的NameNode把所有元数据放在内存里单集群能支撑的文件数大约在数亿级别对大多数离线场景够用。而对象存储的元数据集群是水平扩展的文件数量可以达到百亿甚至千亿级别。2.4 一致性分布式最难的那道坎分布式系统还有一个绕不开的问题三个副本之间怎么保证数据一致。你写了一条数据客户端返回成功但这时候如果只写成功了两个副本、第三个副本还没跟上读请求恰好打到了那个落后的副本上读到的就是旧数据。这就是不一致。要理解分布式存储的一致性CAP理论是个绕不开的框架。C一致性、A可用性、P分区容错性三者最多取其二。网络分区是常态所以P必须选剩下的就是C和A之间做取舍。大多数分布式存储系统在实际设计时用的方案是“多数派确认”也就是Quorum机制。写入时只要多数节点确认写入成功就可以向客户端返回成功读取时也需要读取多数节点然后根据版本号判断谁的数据最新。很多系统把写副本数设为2、读副本数设为2一共3个副本这样读写都能满足多数派条件即使某个节点落后了读到的也是多数节点里最新的数据。这里有个工程上的重要结论副本数和读写确认数决定了系统的一致性等级。如果写确认数等于副本数就是强一致如果写确认数小于副本数就是最终一致。你在选型时要明确业务到底能不能接受“更新后短时间读到旧值”——比如用户余额查询这种场景强烈建议用强一致的方案而浏览量计数、日志存储这类场景最终一致完全够用。3. 主流分布式存储技术选型对照3.1 HDFS大数据离线处理的事实标准HDFS在分布式存储里的地位就像文件系统之于操作系统几乎所有大数据离线计算都建立在它上面。HDFS适合什么场景大文件、顺序读写、一次写入多次读取、离线批处理。典型的就是日志入库、特征数据存储、数仓底层数据落地。它不适合什么场景低延迟随机读写、大量小文件存储、频繁修改文件内容。HDFS的优点非常鲜明与MapReduce、Spark、Flink这些计算引擎集成得最成熟机架感知做得细命令行和API生态完善社区资料多到只要你肯搜就没有找不到答案的问题。缺点是元数据服务有内存上限约束对亿级以下文件数没问题但如果你的文件数是个天文数字就得考虑对象存储或者加联邦机制。如果你走的是大数据开发路线HDFS是必须熟练掌握的。学习路径一般是从“会用命令”开始到“理解块与副本”再到“能看懂NameNode日志做故障排查”最后到“参与集群容量规划与参数调优”。3.2 对象存储云原生时代的通用底座对象存储是过去十年里增长最快的存储类型它把数据抽象成“桶”和“对象”每个对象有唯一的Key通过HTTP API读写。对象存储最大的优势是近乎无限的扩展能力。它不像HDFS那样有一个集中式的元数据瓶颈对象存储的元数据和数据本身都是分片分布式的加机器就能扩容容量和性能可以随着集群规模线性增长。另一个优势是访问协议标准化。业界大量对象存储产品都兼容同一套HTTP对象接口这意味着你在一家平台写的接入代码迁移到另一家平台几乎不用改。很多云厂商的底层存储、大数据平台的备份存储、容器集群的镜像仓库都构建在对象存储之上。对象存储适合海量非结构化数据、冷热分层数据、静态资源、备份归档、数据湖底座不太适合需要强一致性的频繁更新场景也不适合跑在它上面做复杂计算计算引擎会优先把数据拉到本地再做计算。如果你要做技术选型一个接地气的建议是业务数据量大且增长快速、需要对接云上生态优先考虑对象存储数据以大批量离线分析为主、计算引擎已经围绕Hadoop生态搭建优先选HDFS既需要大容量存储又需要实时查询部分热点数据那就要做冷热分层把热数据放分布式数据库或本地缓存把冷数据放对象存储。3.3 分布式数据库与列式存储不只是存储严格意义上分布式数据库不算纯粹的存储系统但它们底层同样是分布式存储架构在实际项目中经常和HDFS、对象存储配合使用所以值得在这里提一句。HBase这类宽表存储适合海量结构化数据的实时随机读写底层依赖HDFS但引入了Region分片和LSM树写优化解决了HDFS不支持随机写的问题。ClickHouse这类列式存储则完全不同它牺牲了单条数据的更新能力换取了极致的大宽表聚合分析速度。选型的时候你需要先想清楚业务到底是“存了为主偶尔查下”还是“高频读写必须快”。前者用HDFS加对象存储就够后者就一定要上分布式数据库或列式存储。很多团队一开始用HDFS存明细数据结果业务侧要求毫秒级查询最后不得不加一层预聚合缓存或者引入列式存储做加速这个弯路我在不少项目里看过。我整理了一个快速选型表方便对照维度HDFS对象存储分布式数据库列式存储适合数据形态大文件、离线批量海量非结构化、归档结构化、半结构化访问模式顺序读写HTTP随机读写实时读写/分析查询一致性写后读一致多数场景最终一致多数派一致或强一致扩展性依赖元数据节点近乎无限水平扩展典型成本存储成本高但计算友好存储成本低存储和计算成本都偏高常见用途数仓底层、计算输入数据湖、备份、静态文件实时查询、在线分析4. 动手实践搭建一套可用的分布式存储环境4.1 环境规划与基础配置理论讲再多不如动手搭一个真实环境。以下我以HDFS为例演示一个三节点的最小分布式存储集群搭建过程这套环境足够用来理解分片、副本、元数据这些核心概念。集群规划采用一主两从结构。节点信息如下主机名IP角色硬件配置node1192.168.1.101NameNode SecondaryNameNode4核8GB100GB磁盘node2192.168.1.102DataNode4核8GB200GB磁盘node3192.168.1.103DataNode4核8GB200GB磁盘操作系统选择CentOS 7.9或兼容版本JDK安装1.8版本Hadoop版本选择3.3.x。这里有个经验性和大家分享一下学习环境不要用特别新的版本很多教程和资料都是围绕稳定版本写的版本太新容易踩到一些网上还查不到的坑。基础配置主要有三块。第一配置主机名映射在三台机器的/etc/hosts里添加三行IP与主机名映射。第二配置SSH免密登录从node1可以免密登录到三台机器。第三关闭防火墙和禁用SELinux这一步在真实生产环境要谨慎但在学习环境能省掉大量排查时间。4.2 核心参数配置与启动验证解压Hadoop安装包后需要修改以下几个核心配置文件。第一是hadoop-env.sh主要设置JAVA_HOME指向你安装的JDK路径。第二是core-site.xml核心配置是默认文件系统地址configuration property namefs.defaultFS/name valuehdfs://node1:9000/value /property property namehadoop.tmp.dir/name value/data/hadoop/tmp/value /property /configurationfs.defaultFS指定了客户端访问集群的入口hadoop.tmp.dir则是元数据和数据块的根目录注意它默认是在/tmp下重启机器会被清空生产环境一定要改到数据盘。第三是hdfs-site.xml关键配置是副本数和NameNode元数据路径configuration property namedfs.replication/name value2/value /property property namedfs.namenode.name.dir/name value/data/hadoop/name/value /property property namedfs.datanode.data.dir/name value/data/hadoop/data/value /property /configuration这里有个容易犯的错如果你只有两个DataNode却把副本数设成了3HDFS依然能启动但控制台上会一直告警部分块无法达到期望副本数。学习环境副本数设2就够了。第四是workers文件把node2和node3写入这个文件它指定了哪些节点是DataNode。这里要注意老版本这个文件叫slaves3.x版本改成了workers网上很多旧教程会在这里误导人。配置完成后先格式化NameNode然后通过脚本启动集群。启动后可以用jps命令验证进程状态node1上应该有NameNode进程node2和node3上应该有DataNode进程。再把node2和node3的DataNode启动起来这样一个最小的分布式存储集群就搭好了。这时打开http://192.168.1.101:9870就能看到集群总容量、已用空间、存活节点数量、块数量这些信息。4.3 数据写入与读取验证集群启动后测试一下真实的数据写入和副本分布。创建一个测试目录上传一个文件然后查看文件的块信息hdfs dfs -mkdir /test hdfs dfs -put /opt/test_data.csv /test/ hdfs fsck /test/test_data.csv -files -blocks -locationsfsck的输出会告诉你这个文件被切成了几个块每个块在哪些节点上各存了几份。如果一切正常你会看到每个Block有2个副本并且两个副本分别落在不同的DataNode上。这就是分布式存储最直观的验证方式——同一个文件物理上被切成了多块每块又有多份分散在不同的机器上。再测试一下故障容忍。手动kill掉一个DataNode进程然后等一两分钟再执行fsck命令你会发现系统自动把缺失的副本重新复制到了其他节点副本数恢复为2。这个实验做完你对“自动故障容错”这个概念的理解会远超看十篇文章。5. 生产环境常见的坑与排查经验5.1 小文件问题千万级文件数的隐形杀手生产环境里最典型的坑就是小文件问题。一个300MB的日志目录如果被切成上万个10KB的碎片文件对HDFS来说就是灾难。原因在于每个文件、每个文件块都要在NameNode内存里占一份元数据。一个文件至少占用约150字节的NameNode内存一万个文件占了元数据空间还不算大但一亿个小文件就会把NameNode内存吃干净。而真正可怕的是每一个小文件在计算时都会启动一个任务任务调度开销远比数据读取开销大整个集群的CPU都在做无用功。解决小文件问题有几种常见手段输入侧合并小文件比如用CombineTextInputFormat写入侧定期将小文件合并为大文件再入库离线场景直接通过数据同步工具把一堆小文件的目录灌进Hive/Spark数仓让引擎自己合并。从根本上说小文件不是存储问题而是写入策略问题。源系统产生小文件的频率不是你能控制的但你怎么落地它们是可以设计的。在数据接入层加一个“缓冲-合并-写入”的流程就能避免99%的小文件灾难。5.2 数据倾斜与热点集群里一半忙一半闲数据倾斜是计算层问题但它也会反过来影响存储层。大量任务都在读某一个热点节点上的数据块这块磁盘成了瓶颈其他节点却闲着。存储层面的预防手段主要有两种。第一是让写入数据在分片时尽量分散。HDFS的Block天然按大小切分不容易出现单块热点但如果你用HBase这类按范围分片的系统要注意RowKey设计避免连续写入集中到同一个Region。第二是定期做集群Balancer把数据从高占用节点平衡到低占用节点。生产环境里我见过一个很典型的场景某业务每天导入一张大表主键是自增ID按主键范围分片后新数据永远落在最后一个Region上这个Region所在节点写入永远是瓶颈其他节点完全空闲。这种问题不是加机器能解决的必须从分片键设计上入手。排查数据倾斜有一个比较直接的方法在NameNode的Web UI上查看各个DataNode的已用容量分布如果节点间容量差距超过20%就可以考虑执行Balancer了。5.3 磁盘不均衡与副本失败脏盘是第一大元凶一个集群在运行半年后各节点磁盘使用率大概率会出现明显差异。原因很现实删除文件、块迁移、节点上下线都会导致数据分布不均衡。HDFS提供了Balancer命令可以通过调整块的存储位置来让各节点磁盘使用率达到均衡。需要注意的是Balancer会占用网络和磁盘IO生产环境建议在低峰期执行并且要限制带宽hdfs balancer -threshold 10 -bandwidth 50MBthreshold参数表示节点间使用率差距的目标值设为10表示容忍10%以内的差异设太大会出现局部热点设太小Balancer会频繁搬迁块反而影响性能。副本失败的问题也很常见。你会在NameNode日志里看到“Replication factor not met for block”的WARN原因通常有三种第一DataNode磁盘损坏或节点离线需要先修复节点再等系统自动补副本第二副本数设置过低比如只有1一旦那块盘损坏数据就永久丢失第三磁盘空间不足导致新的副本无法落盘。排查时先df -h检查磁盘使用率再jps确认DataNode进程存活最后hdfs fsck扫描全量文件副本状态按顺序来基本都能定位。5.4 权限与安全配置测试环境无感生产环境要命很多人在搭建学习环境时都习惯于直接关闭权限校验因为这样用起来方便。但在生产环境权限配置缺失会带来实实在在的安全事故。HDFS默认的权限模型和Linux类似有user、group、other三级权限。建议至少做到以下几点给不同业务线建不同用户和目录业务A不能读业务B的数据配置NameNode的RPC端口只对内网开放不暴露到公网启用回收站机制fs.trash.interval设置成至少24小时防止误删文件后无法恢复。回收站这个配置很容易被忽略但它真的能救命。我有一次手动清理临时目录时多删了一级路径差点把一个数仓的原始数据层清掉就是因为有回收站管理员才能完整恢复。生产集群的回收站保留时长建议不少于7天。6. 写在最后一些个人体会做分布式存储相关的工作时间越长越觉得学习路线比天赋重要。很多人在接触分布式存储时一上来就啃论文、看源码、背概念结果越学越抽象最后反而失去了动手的信心。我的经验是先搭建一个真实环境把文件传进去、把节点杀掉、看系统如何自愈把“分片、副本、元数据、一致性”这些概念亲手验证一遍再回头看原理就会顺畅很多。还有一点想和准备往这个方向深耕的读者分享分布式存储只是数据技术栈里的一个底座你学会了它还要继续理解它和计算引擎的配合方式、它之上的数据治理方案、以及它在整个数据平台里的架构位置。存储、计算、调度、治理这些词连起来才是一个完整的大数据工程师的能力拼图。但如果非要选一个最值得花时间打牢的基础模块我仍然会把票投给分布式存储。原因很简单不管计算引擎怎么换、框架怎么演进数据最终还是要落在某个存储系统里谁能把数据稳稳地存住、高效地取回谁就拿到了这个领域最底层的主动权。迈过这道坎后面的路会越走越宽。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →