ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

海量数据存储架构设计与选型实战:分片、副本、冷热分层全解析

海量数据存储架构设计与选型实战:分片、副本、冷热分层全解析 1. 选型之前先想清楚你的数据到底有多“多”1.1 量级预判从GB到PB方案完全不同很多朋友上来就问我“海量数据存储到底该选什么”我一般会先反问一句“你觉得你的数据是海量到底是多少”这不是抬杠而是存储领域有一个很残酷的现实——不同量级的数据对应的解决方案是天壤之别。你手里是几个TB的业务数据和几个PB的日志文件要面对的问题完全不同。几个TB的话说实话一台配备大容量硬盘的服务器用ZFS或Btrfs做快照和RAID可能已经绰绰有余了没必要上来就搞分布式。但到了几十TB到几百TB单台服务器的容量、性能、故障恢复能力都会到极限这时候就需要认真考虑分布式文件系统或对象存储。到了PB级以上那就不是简单“上HDFS还是Ceph”的问题了而是需要从网络、机房、机架、存储介质、数据治理多个维度做整体设计甚至还要考虑数据在哪个城市、哪个机房跨地域怎么调度。我这些年做过一个很接地气的估算方法先把业务数据增长速度假设为线性增长按最坏情况比如每年翻倍甚至翻三倍乘一个安全系数算出来的数字再翻一倍作为容量规划基线。这么做看起来很保守但经历过几次“存储容量告急临时扩容到半夜”的惨痛教训之后你会发现这个保守是值的。存储这行最怕的不是买多了浪费而是算少了之后业务侧直接卡脖子。1.2 访问模式决定了存储架构的走向除了数据量另一个更重要的维度是你的数据是怎么被读和写的。我见过太多团队把业务场景没想清楚就上了一套看起来很厉害的存储系统结果性能一塌糊涂还以为是系统不行。我习惯把访问模式分成几类来看大批量顺序读写的分析场景比如跑离线报表、机器学习训练的数据集这种典型是大文件、顺序IO、写一次读多次HDFS这类分布式文件系统是经典选择。非结构化数据的存储场景比如图片、视频、用户上传的文件、网关日志特征是单文件大小参差不齐、总量增长快、读多写少对象存储是标配。在线交易类的高并发结构化数据比如订单、用户信息、账户余额要求强一致、事务性、低延迟这种要用分布式关系型数据库或NewSQL而不能硬塞到文件系统里。还有一类容易被忽略的是数据有三个月热度和三年冷度。比如监控数据、历史订单最近三个月频繁访问之后几乎不碰。如果不做冷热分层把所有数据都放在高性能存储上成本会高到让你怀疑人生。这块下面单独展开讲因为它是成本控制的真正命门。2. 主流海量数据存储方案盘点与对比2.1 分布式文件系统扛起通用存储的半边天先说说分布式文件系统。这里最典型的代表就是HDFSHadoop分布式文件系统此外还有GlusterFS、CephFS这类方案。它们的共同点是把很多台服务器的本地磁盘聚合成一个大文件系统对外暴露一个几乎无上限的目录树支持大文件顺序读写。我为什么先说它因为很多团队的第一套海量存储方案就是从HDFS起步的。HDFS的设计哲学很有意思它默认文件是海量的、追加写入的、很少修改的所以它把大文件分割成128MB或256MB的数据块分散存储在多台节点上再通过固定的副本策略保证可靠性。用HDFS时有个关键点要提醒它是为“大文件”设计的对小文件极其不友好。如果你一个目录下有几十万个小文件每个只有几KB那NameNode元数据节点的内存会直接被打爆因为每个文件、每个数据块都要在内存里记录元数据。我见过一个团队把大量小图片直接往HDFS里塞最后NameNode堆内存涨到几十GBGC频频卡顿整个集群都在“呼吸都困难”的状态。后面我会在“常见问题”部分专门讲小文件怎么治。CephFS的问题则相反它靠的是动态元数据分片性能调优的复杂度高不少。如果你团队里没有一个对Ceph内部机制门儿清的人我建议还是别在生产环境里贸然用CephFS跑核心业务Ceph的对象存储倒可以放心用。2.2 对象存储海量非结构化数据的标配对象存储这几年几乎成了互联网公司存储层的地基。你可能没直接接触过但你用过网盘、发过图片、传过视频背后基本都是对象存储在工作。它的核心概念是“BucketKey”也就是一个存储桶里面装无数对象每个对象通过一个唯一的key来访问没有目录树的概念也不支持实时修改文件通常只能覆盖写或删除重建。对象存储最大的几个优点我实际体验下来非常香接口极简基本就是GET、PUT、DELETE几个操作学习和接入成本低。容量和吞吐近乎无限扩展通过数据的分布式打散加上调度层做负载平衡几千台节点共用一个空间是很常见的事。数据高可靠默认多副本或纠删码跨机架、跨机房容灾单块硬盘坏了根本不叫事。生态成熟几乎所有大数据组件都支持对接S3协议你可以把它当存储底座来用。现在市场上常见的有开源Ceph RGW、MinIO以及各大云厂商的S3兼容服务。如果你们团队没有专门的存储组又想快速搭一套我比较推荐从MinIO或Ceph RGW的S3协议方案入手业务代码不用绑定具体厂商将来需要上云或者换平台改动量很小。我自己在实际项目里就吃过“用了厂商私有协议后来迁移时几乎要重写整个存储层”的亏所以对“接口标准化”这件事特别敏感。2.3 分布式数据库结构化数据的主战场如果数据是结构化的、需要频繁增删改查那文件系统和对象存储都不合适必须交给数据库来做。这里我分成两派说分布式关系型数据库典型如TiDB、OceanBase、CockroachDB。它们保持了SQL和事务特性同时靠自动分片把数据打散到多台机器上。适合那种业务量已经大到单机数据库扛不住、又不想引入分库分表中台成本的团队。NoSQL数据库典型如Cassandra、ScyllaDB以及国内用得比较多的HBase。它们通常不支持传统事务但换来的是极强的写入吞吐和灵活的Schema。适合时序数据、消息数据、用户行为日志这类对一致性要求没那么苛刻的场景。实际做选型时我的经验是先问业务“一条记录能不能拆成独立的一行处理”如果能用NoSQL把钱省下来如果业务特别依赖跨行事务和复杂SQL就直接上分布式关系型数据库别自己拿应用层做事务补偿那是踩不完的坑。有一年我们接了一个订单中台项目业务要求强一致、跨分片事务我们试过用Cassandra加应用层协调搞了一个多月测试阶段就发现了十几个并发一致性问题最后还是老老实实切到TiDB一周就搞定了核心链路。专业的事交给专业的系统这是存储选型最朴素的真理。2.4 冷热数据分层成本与性能的平衡术这是我要重点强调的一个理念因为太多团队把“海量存储全部放高性能存储”这个错误的等式刻在脑子里。实际上大部分数据是有生命周期的。拿日志数据来说今天的日志被实时检索的概率很高一个月的日志偶尔被翻出来排查问题一年前的日志几乎只有审计和合规才会碰一下。冷热分层就是要把不同“温度”的数据放在不同的介质上热数据访问频繁放在NVMe SSD或高性能分布式存储上保证毫秒级响应。温数据偶尔访问放在普通SATA SSD或大容量HDD上追求单位容量成本。冷数据很少访问放到对象存储的冷存储层甚至用磁带归档。访问一次要等若干秒甚至分钟但成本可以做到热存储的十分之一。我在一个项目里做过对比一套全热存储的方案每年存储成本约120万元采用冷热分层后80%的冷数据下沉到对象存储冷层存储成本直接降到40万元出头而业务延迟几乎没受影响。这个账任何一个稍微有点规模的公司都应该认真算一算。弹性、扩展性不是第一位的成本结构才是长期运营的第一位。3. 核心架构设计把“海量”拆成“可管理”3.1 数据分片Sharding的策略与边界有了大概的选型方向接下来就进入架构设计的核心环节了。无论是分布式数据库还是分布式存储系统底子里都离不开一个动作——把数据分片。分片的目的很简单让每台机器只负责一部分数据这样单机的性能瓶颈就不会拖垮全局。分片策略常见的有三种哈希分片根据key的哈希值取模落桶。优点是数据分布均匀缺点是范围查询要跨多个分片。范围分片根据key的排序区间分片比如按用户ID的前几位划分。范围查询友好但可能产生热点分区。目录/映射分片通过一个中间层维护key到分片的映射关系灵活度高但多一跳延迟。我在实践中对分片有一个很深的感悟没有哪一种策略是万能的关键是分片键的选择。分片键一旦定错后续要改几乎是灾难级别的。我之前接手过一套用户中心系统原来按用户ID哈希分片但业务里有一个很常见的操作是“查某一天所有新增用户”这个查询要扫全部分片每次都慢得像跑马拉松。后来我们做了个折中把数据按时间维度先分区再按用户ID哈希分桶相当于两级路由才把这个痛点解决掉。分片数量也要认真算。一个经验值单分片的数据量控制在200GB以内每秒读写控制在几千次以内。容量越过这条线扩容成本和迁移风险就开始指数级上升。别贪多分片不是越细越好分片太多会导致元数据膨胀、跨分片协调开销变大整体性能反而下降。3.2 副本与纠删码可靠性的两种实现路径数据放在单块硬盘上肯定会坏所以海量存储系统必须用冗余来对抗硬件故障。目前主流可靠性手段就两条路多副本和纠删码。多副本最简单粗暴同一份数据存三份分别放到不同机架甚至不同机房。读请求可以从任意一个副本读写请求要等所有副本确认。三副本的存储有效率只有1/3也就是说你买12块盘真正“有用”的只有4块的容量成本相当高。**纠删码Erasure CodingEC**是另一条路它的思想跟RAID类似把数据拆成k个数据块外加m个校验块任何一个块丢了都可以通过剩余块计算出来。比如常见的42配置写4块数据、2块校验存储有效率是4/6约67%比三副本的33%高了一倍。代价是数据恢复时需要计算CPU开销大重建时间也长。那么怎么选我的建议是热数据、核心数据用多副本。因为读取延迟低、恢复快对用户体验敏感的场景多花点存储成本是值得的。冷数据、备份数据用纠删码。这类数据访问少CPU开销可以接受但容量成本能省出很大一块。这块要特别注意翻车点不要在一个纠删码组里放同一个机架的节点。我遇到过一次事故一个42的EC组里有三块盘在同一个机架机架交换机故障直接导致整个数据组变成只读业务影响面非常大。后来所有的EC策略配置都在代码层面强制做故障域隔离再没出过同类问题。故障域这个东西平时不起眼出事就是要命。3.3 元数据服务最容易忽略的瓶颈点很多人设计海量存储系统的时候第一反应是关心数据怎么分布、怎么读写但往往忽略了一个关键角色——元数据服务。元数据就是“关于数据的数据”比如文件路径、数据块位置、对象key的索引、分区信息等。数据量越大元数据本身就会膨胀成一个不容小觑的问题。举个具体例子HDFS里每个文件的元数据大概有几百字节到1KB每个数据块还要额外记录。如果你的集群里有1000万个文件光元数据就占到几个GB到十几GB内存。而这个元数据服务通常集中在少数节点上比如NameNode它一旦满了、慢了整个集群所有读写操作都会卡住因为任何一次读写都要先跟它打交道。所以我的经验是元数据服务的设计要当成一个独立的子系统来对待而不是顺带想想。具体来说有几点元数据要独立部署不要和业务数据混在一起否则磁盘故障时很容易同时损失数据和元数据。元数据的存储引擎要选高并发、低延迟的比如内存数据库加持久化日志的方案。如果元数据量真的非常大就要考虑元数据分片。CephFS的多个MDS、HDFS的Federation本质都是为了把元数据压力分散开。元数据的备份和容灾比业务数据更优先。业务数据丢了部分还能重建或回源元数据丢了整个存储系统就像一本书没有了目录有内容也找不回来。这块我交过学费。早期我们自己用HDFS搭了一套小集群想着“数据反正有多副本”就没太在意NameNode的元数据备份。结果NameNode所在机器磁盘损坏加上我们没做异地备份整个集群的目录结构全没了虽然数据块还在但没法知道哪个块属于哪个文件。最后只恢复了约八成数据剩下的只能算“永久失踪”。从那时候起我给自己定了一条铁律任何存储系统的元数据必须定期备份到完全独立的位置并且要演练恢复流程。4. 实操落地一套海量数据存储方案的设计全过程4.1 需求梳理与容量规划前面讲了原理和方案这一节我按真实项目的方式带大家走一遍完整的落地方案。假设我们是一家做视频监控的创业公司每天产生约5TB的视频文件和约500GB的索引数据需要保留90天要求随时回放最近7天的视频7天到90天的视频允许延迟几秒加载。首先做容量规划。每天5.5TB、保留90天总容量就是5.5TB×90495TB。但你必须算上副本或纠删码冗余。如果热数据最近7天约38.5TB用三副本那实际占用是38.5×3115.5TB温数据8-90天约456TB用42纠删码有效率是67%实际占用约456/0.67681TB。合计需要约797TB的裸容量。考虑85%的磁盘可用率最终需要采购约940TB的裸容量。注意这还没算预留扩容空间我通常会在需求外再多留30%。这样做规划你才能对硬件采购预算心里有底也才能跟老板讲清楚“为什么看起来只有500TB的数据却要买快1000TB的盘”。然后是性能规划。最近7天的数据要被随时回放假设高峰期并发回放200路视频每路码流8Mbps那读吞吐大约是200×8Mbps1.6Gbps加上索引和数据库的读写压力我一般会把整体规划吞吐定到峰值乘1.5倍。这些数字就是后续选型的基本输入也直接影响网络拓扑和盘型选择。4.2 硬件选型与集群拓扑设计在做硬件选型前要先把一个概念定死——存储系统是木桶效应特别明显的系统你的短板在哪全集群的上限就在哪。网络方面现在海量存储基本起步就是25GbE规模大的直接上100GbE。如果你还在用万兆甚至千兆建议认真考虑一下数据吞吐算下来万兆网络可能只能支撑不到1GB/s的聚合带宽而一个几十节点的集群分分钟把网络打满。我见过小团队为了省成本存储节点配了万兆网卡但业务侧接入交换机只有千兆最后整个集群IO上不去排查了半天才发现瓶颈在接入交换机端口。网络这块宁可超前不要落后。盘型的选择也要分层。热数据节点全NVMe SSD温数据节点用大容量HDD混合少量SSD做缓存冷数据节点用最大容量的企业级HDD。这看起来很贵但实际上比所有节点都堆SSD要便宜得多。存储节点建议每台容量控制在300TB左右裸容量太多会导致故障恢复时间过长太少又浪费管理成本。拓扑设计上我坚持一个原则控制故障域半径。至少划分到机架级别一个机架的节点不应该承担同一个数据分片的全部副本或纠删码块。有条件的话还应该把热数据集群和温冷数据集群分开避免热数据频繁读写时跟批量数据迁移抢IO。另一个细节是存储集群的交换机要预留专门的维护端口和管理网络否则哪天要重启某台交换机你连管理口都进不去MySQL停机维修的感觉会很酸爽。4.3 数据迁移与上线路径方案落地不只是搭新集群还涉及从旧系统迁移数据这一步出问题的概率特别高。我给你一条我在多个项目里验证过的迁移路径第一步同步双写。在存储层旁边搭一套消息管道业务写入新老存储各一份老存储上保留全量数据。第二步跑数据一致性比对。借助校验工具抽样甚至全量比对新旧两个存储上的数据确保双写阶段没有漏写、错写。第三步逐步切读流量。先把5%的读流量切到新系统观察一段时间如果延迟、错误率、系统负载一切正常再逐步加比例10%、30%、50%、100%。这个阶段需要精细化监控每一项指标都要有明确的阈值不能拍脑袋切流。第四步老系统只读保留观察一个月。确认新系统稳如老狗后再下线老系统。注意这个阶段别急着把老系统释放掉数据放着不花钱删了可就追不回来了。整个迁移过程中最常见的坑就是大家都在等“全部迁移完”的那一刻但真正重要是“什么时候开始切”。我的经验是小步快跑千万别做“烧鸡式”的一次性大切换那太容易出大事了。还有迁移期间要保留完整的操作日志哪个时间点改了什么、谁操作的一清二楚出了问题才能快速定位。经历过一次迁移事故之后你会发现“可追溯”这三个字比黄金还值钱。5. 常见问题与排查经验实录5.1 小文件堆积导致的性能悬崖作为第一个问题小文件也是海量存储里出现频率最高的问题。它具体指什么通常是指文件大小远小于存储系统块大小的情况比如HDFS是128MB的块你却存了几KB的文件。分布式文件系统里每个小文件都要占一条元数据记录小文件多了会直接把元数据服务打爆而读一个小文件经历的网络往返和故障次数可能和大文件几乎一样IO成本被放大了几十倍甚至上百倍。治理思路不复杂核心是小文件要先合并成大文件再入存储。我记得一个具体的案例某团队每天产生2000万个小日志文件直接写入存储以后光元数据就占掉50GB内存。我们后来接入一个日志采集组件按窗口做批量攒批每五分钟把同类型日志合并成一个大的序列文件再配一个索引文件记录偏移量。这样一来2000万个小文件变成了不到300个文件元数据占用降了两个数量级。当然也要注意合并处理并不是银弹。需要有配套的查询机制比如索引表才能保证处理完后还能按需读取。海量存储世界的矛盾往往就是这样存储要的是大块业务产生的是小块中间需要一个缓冲层。5.2 数据倾斜热点分区的隐形杀手第二个常见问题数据倾斜也是很要命的。所谓倾斜就是分片后大量数据或请求集中到少数几个节点上。比如你在社交App里按“用户ID哈希”分片某个头部用户贡献了千万级粉丝和超高频访问他所在的节点就会被压垮整个集群的均衡也直接失效。排查倾斜的经典方法是在监控面板上看各节点的吞吐和容量分布如果出现明显的“二八现象”——20%的节点承担80%的流量——基本可以确认有数据倾斜。另外如果某几个节点的磁盘使用率显著高于平均水平也是倾斜的信号。解决方案也分几层如果是热点Key问题可以在应用层把热点Key加上随机后缀拆分到多个分片上读的时候并行读再汇总。这招能很大程度缓解热点。如果是数据分布不均就要检查分片键的选取。比如选择了枚举值很少的字段性别、状态码做分片键那基本注定倾斜尽早换掉。如果是范围分片带来的局部热点可以引入“分片路由中间层”自动把落到热点分片的数据再做一次拆分。我自己的经验是分片键设计时不要只看查询效率一定要看一眼业务数据分布。凡是枚举值分布极少、或单个key访问量极大的字段都谨慎使用。5.3 故障域设计与数据恢复优先级第三个要跟大家分享的是故障域设计和数据恢复这个通常是运维期才会被发现的问题。所谓故障域简单理解就是一个故障能够影响到的最大的范围。一台机器坏了影响该机器一个交换机坏了影响整个机架一个机房的制冷坏了影响全机房。存储系统在设计副本和纠删码时必须把这些故障域考虑进去确保同一个数据的多个副本不在同一个故障域内。很多刚接触这块的朋友会忽略一个细节故障域不只是物理上的还可能跟软件升级相关。比如你有一个脚本会把相同机架上的终端统一升级固件如果你的副本恰好同一机架就会在升级时出现“两个副本同时被升级流程动”这种隐藏风险。所以不仅是故障场景变更场景也要有副本隔离意识。另外我总结了一个经验数据恢复的优先级比数据写入的优先级要高。当集群中有节点故障要重建数据时很多人把注意力放在接收新写入上结果一个副本恢复拖了好几天期间一旦再挂一个节点整份数据就直接变成只读甚至丢失了。正确的做法是在配置中心里让恢复任务的带宽配额高于日常写入加任务队列和重试机制同时做好监控统计数据恢复任务的剩余时间超过预期就要立刻处理。故障处理完毕还要记得在一个稳定周期后再做数据校验防止数据恢复过程中出现的“静默损坏”遗留下来。6. 我踩过的一些坑和最终建议说实话写到这里我脑子里又冒出了不少当年踩坑的画面。2017年有一次我们上了一个新集群因为配置里少了“数据均衡自动触发”的开关过了快一个月才被监控告警系统提醒“集群节点间存储利用率差距过大”当时已经有三个节点磁盘直接写满了。我们紧急手工触发均衡任务结果又碰上升级窗口双重压力下一台节点起不来整整折腾了一个通宵才恢复。复盘时最扎心的一句话是这个开关默认值不是我们以为的那个“已开启”。所以我特别想把这几条建议送给大家也是我实际操作中反复验证过的第一存储系统的所有核心配置不要相信默认值。每个参数都要想一想如果它本来的默认配置不适合你的场景默认值就会在某一天变成事故的源头。尤其是数据均衡、故障自动恢复、告警阈值这几类。第二无论方案介绍得多么天花乱坠一定要做故障演练。拔一盘、拔一节点、拔一交换机甚至模拟一个机房断电看看系统是怎么响应的数据能不能恢复恢复时间是多少。演练发现的问题才是真正需要解决的问题。我知道这件事很麻烦但真正遇到问题时你会感谢当初演练的自己。第三成本优化的优先级其实应该排在性能优化之前。大部分海量存储场景里“能跑”和“跑得快”之间隔着几倍的成本差距而“够用”和“极致性能”之间的差距往往业务体感并不明显。我的习惯是先满足容量需求再保证可靠性最后在满足SLA的前提下尽量压低成本。顺序反了钱不够的时候一定会后悔。第四无论用哪套存储方案一定要把文档和架构图沉淀下来。别指望半年后的自己还记得当初为什么这么选型、为什么这里用三副本、为什么那套集群没有开自动均衡。存储系统动辄跑好几年交接、复盘、再演进没有文档寸步难行。海量数据存储没有标准答案每个团队、每个业务都有自己的约束和优先级。但我相信把量级算准、访问模式想清楚、选型做对、架构踩稳、运维留一手你就已经比绝大多数团队走得稳了。如果你正在经历存储瓶颈或者正准备做新的存储架构希望这篇文章能帮你少走一些弯路。欢迎在评论区聊聊你遇到过的存储翻车事故我每条都会好好看。
返回列表