1. 存储类型全景解读块存储、文件存储与对象存储1.1 三种存储类型到底差在哪里很多人一接触数据存储就先被概念劝退了。什么块存储、文件存储、对象存储听着像三个完全不相干的东西其实用生活里的场景一对比就特别清楚了。块存储就好比给你一块空地地面画好了格子你可以直接在任意格子里写东西。系统层面看到的是一个裸设备没有目录没有文件名只有一个个固定大小的块。数据库、虚拟机镜像这类对延迟敏感、对随机读写要求高的业务几乎都跑在块存储上。因为它的路径最短IO路径上没那么多中间层性能最直接。文件存储则是我们日常接触最多的形态。它有个层级目录有文件名、文件大小、修改时间这些元数据访问方式就是标准的文件和目录操作。NFS、SMB这些协议都属于文件存储的范畴。它最大的优势是通用、好管理业务系统不需要做任何改造就能挂载使用。对象存储是这几年的香饽饽它的逻辑模型是桶 对象每个对象有唯一的Key没有层级目录的概念。访问走的是HTTP API天然适合海量非结构化数据。图片、视频、备份归档、日志这类数据用对象存储非常划算。它最大的特点是扩展性好几乎可以无限扩容而且自带高可用和强一致性的能力。让我用一个通俗的类比帮你把这三者串起来块存储是工地上的钢筋水泥你可以随意倒腾但需要自己盖楼文件存储是已经装修好的房间按门牌号找东西就行对象存储是一个巨大的仓库每个包裹贴上唯一单号扔进去取的时候报单号就能拿到。三者的本质差异在于数据如何被组织、寻址和暴露给上层应用。1.2 存储介质的演变从机械硬盘到NVMe理解存储类型之后还得理解底下那层物理介质。毕竟再好的架构最后数据还是要落在某种硬件上。机械硬盘的时代核心技术是盘片旋转加磁头寻道。它的顺序读写还不错但随机读写一旦上来磁头到处找位置性能和延迟就非常难看。早期的数据库运维大家都会特别在意随机IOPS这个指标因为机械硬盘的随机IOPS通常只有一两百稍微上点并发就卡死了。这也是为什么那时候要做那么多缓存、索引调优——本质上是在弥补硬件短板。SSD的出现把这个问题打掉了一大半。闪存颗粒没有机械运动随机读写的性能比机械盘高出一两个数量级。用得多了以后大家开始关注另一个问题SSD的寿命。每个闪存颗粒的擦写次数是有限的频繁写入会快速消耗寿命。所以现在存储系统里都有磨损均衡、写入放大控制这些机制目的就是把写入压力均匀分散到所有颗粒上。然后是NVMe协议。以前SSD走SATA接口协议本身是给机械硬盘设计的即使硬件很快接口和协议也限制了发挥。NVMe是专门为闪存介质设计的协议走PCIe通道延迟能压到几十微秒级别带宽轻松到数GB每秒。我自己的体会是把数据库从SATA SSD迁移到NVMe之后同样的业务压力下响应时间几乎是肉眼可见地掉了一半以上。今天谈存储架构如果不考虑NVMe这一层优化空间是很有限的。1.3 数据存储格式你存下的到底是什么存储介质解决的是数据放在哪儿存储格式解决的则是数据怎么排布。同一个意思组织方式不同性能差异能到十倍以上。拿最常见的关系型数据库举例行存储把一条记录的多个字段连续放在一起适合按行进行增删改查。列存储则把同一列的数据连续存放适合大规模分析场景下只读取部分字段的需求。数据仓库里跑报表用列存比行存快得多因为读取数据量被大幅压缩了。日志、监控、时序数据这一类通常会采用专门的时序存储格式。它按时间维度进行分区、压缩配合降采样、过期清理策略使得这类数据的存储成本可以压得非常低。我见过有些团队把时序数据直接塞关系型数据库结果表越来越大、查询越来越慢最后只能再迁到专门的时序数据库里。对象存储里还要关注数据封装格式和元数据管理方式。比如很多对象存储底层用纠删码来替代多副本同样的数据冗余度下磁盘利用率能从33%提升到80%左右但代价是额外的编码计算和网络开销。所以你看存储这行处处是取舍没有全能的方案只有适不适合的选型。2. 存储架构从单机到分布式再谈云原生2.1 集中式架构与分布式架构的核心差异早期绝大多数业务系统的存储架构都是集中式的。一台高性能服务器、一台盘阵或一个SAN全公司所有数据都在里面。好处是架构简单、一致性容易保证运维也省心。但坏处也很明显单点瓶颈、扩展能力有限、硬件成本高得离谱。我见过有公司核心库一直跑在一台小型机上采购成本上百万不说一旦需要扩容就要停机迁移业务方提前一个月报备运维团队熬夜操作每次都是一场大考。集中式架构在数据量小、并发低的时代是够用的但今天数据量一旦上来它的天花板很快就能摸到。分布式架构的思路是把鸡蛋分到多个篮子里。数据被分片打散到多台服务器上每台机器只负责一部分数据多台机器一起对外提供能力。听起来很美但代价也实实在在摆在那里——复杂性全转移到软件层了。怎么分片、怎么保证副本一致、某个节点挂了怎么恢复、跨节点的查询怎么做每一个问题都比单机时代复杂一个量级。选择集中式还是分布式不是单纯看技术先进性而是看业务需求。数据量几百GB、并发几百的业务用单体存储完全没问题强行上分布式反而给自己找麻烦。我见过不少团队为了简历好看或者跟风在很小的业务上加了一整套分布式存储结果运维成本比业务本身还高。架构选型要克制这一点特别重要。2.2 分布式存储必须解决的三座大山分布式存储之所以难难在三个核心问题上分片、复制、一致性。分片解决的是数据放哪台机器的问题。最常见的策略是哈希分片用一个哈希函数把数据Key映射到不同的节点上。哈希分片的好处是分布均衡、实现简单但坏处是扩展节点时需要重新分布数据。范围分片则把数据按Key范围切段每个段落在不同节点上这对范围查询很友好但容易出现热点。分片策略直接决定了后续的数据均衡、查询效率是存储架构设计里最需要想清楚的一步。复制解决的是数据怎样不丢。每一份数据保存多个副本分别放在不同机器甚至不同机架上。这样一台机器挂了另外的副本还能顶上。副本数量的选择要权衡可靠性跟成本三副本是主流标配空间利用率33%但能容忍同时挂掉两台机器两副本利用率50%可靠性差一些纠删码42配比下空间利用率67%能容忍挂两台但是需要额外的计算资源。从成本角度冷数据用纠删码热数据用多副本是常见的组合策略。一致性解决的是多个副本之间的数据到底以谁为准。强一致性意味着所有副本实时同步读任何一台机器都能读到最新数据但性能会受影响最终一致性允许多副本之间存在短暂的不一致性能好但业务上要能容忍。这中间还有一个经典问题叫脑裂网络发生分区时新旧主节点同时对外服务数据就乱了。所以分布式系统里通常需要引入一个仲裁机制来选出唯一的主节点。这方面已经有很多成熟的中间件比如etcd、ZooKeeper。2.3 架构演进从传统架构到云原生存储看一个行业的架构演进往往能看出技术选型的真实逻辑。早年大家用的是IOE架构也就是小型机加商业数据库加高端存储稳定是真稳定贵也是真贵。后来互联网业务暴增大家发现传统架构扛不住海量用户和快速迭代了于是开始用大量普通服务器替代高端硬件用开源的MySQL、NoSQL替代商业数据库用分布式存储替代集中式存储。这一时期就是现在大家常说的分布式架构替换传统架构。再往后容器化、微服务这些理念逐渐普及存储也跟着进入云原生时代。存储能力不再是某个独立硬件而是作为一种服务通过CSI、CSI接口和Kubernetes向下暴露给应用容器使用。应用不再关心底下的存储设备是什么只需要声明我要多少容量、什么性能等级平台自动帮你分配。存储容量弹性扩缩、按需计费、故障自愈这些能力在过去完全不可想象。微服务架构下存储的设计理念也和单体时代完全不同。每个微服务应该有自己独立的数据库而不是所有服务共享一个庞大的数据库实例。服务之间通过API访问数据或者通过事件机制进行数据同步而不是直接去读取对方的表。这背后的核心考量就是故障隔离和独立演进。一个服务崩了不能拖垮全部服务这是微服务存储设计的铁律。3. 数据存储解决方案场景驱动的选型落地3.1 数据库场景下的存储选型讲存储解决方案永远不能脱离具体场景。不同的业务场景对存储的需求差异非常大。关系型数据库场景下核心诉求是强一致性和事务支持最常见的存储形态是块存储。比如MySQL跑在云服务器上通常会把数据目录放在一块独立的高性能云盘上。这里有个容易被忽略的细节事务日志和数据文件最好放在不同磁盘上避免两个高频写入路径互相争抢IO。我之前排查过一个数据库性能问题检查下来发现数据文件和binlog日志放在同一块盘上IO队列经常被打满后来拆开之后整个系统明显顺畅了。开源分布式数据库场景下比如TiDB、OceanBase它们的存储层已经是一个分布式存储系统了底层节点需要的是本地盘或者高性能存储设备。这种架构下选存储更多的是考虑容量规划、节点故障域隔离、监控告警等方面而不是单纯看某一台机器的IO性能。非关系型数据库场景则更加多样化。键值存储如Redis追求极致的低延迟数据一般放内存持久化用AOF或RDB文件文档数据库如MongoDB天然适合跑在对象存储或文件存储上但要注意索引和热数据还是需要高IOPS的本地存储图数据库的存储更多依赖数据之间的关联性对遍历性能要求高。这些数据库的存储形态各不相同选型时要仔细阅读官方文档推荐的部署方式不要想当然地套用一个方案。3.2 高并发场景下的存储架构思路高并发场景是所有存储架构里面最考验功力的一类。核心思路无非是缓存挡流量、存储保底、队列削峰、分库分表兜底。最基本的思路是引入缓存层。Redis这类缓存系统可以将热点数据放在内存里把绝大多数读请求挡在数据库前面。要注意的是缓存穿透、缓存击穿、缓存雪崩这三类经典问题每一种都有对应的应对方案。比如空值缓存解决穿透、互斥锁解决击穿、随机过期时间解决雪崩。我见过不少系统在这上面栽过跟头都是一些看起来很小的细节没有提前处理流量一起来就爆。流量削峰靠的是消息队列。在秒杀、抢购这类场景下如果所有请求都直接打到底层存储再强的数据库也顶不住。用MQ把请求先收下来以可控的速率慢慢消费底层存储的负载就能保持平稳。这里有个关键点需要注意消费端要支持幂等处理。消息可能被重复投递如果消费逻辑不幂等数据就会乱掉后面排查问题会让你非常头疼。数据量大的场景还要考虑分库分表。当单表数据量超过千万级索引维护成本和查询性能都会明显下降。分库分表的路由规则要提前想清楚按用户ID哈希是常见做法但也要考虑后续扩容时的数据迁移成本。分库分表之后跨库查询、分布式事务的问题也会冒出来这个后面细说。3.3 视频监控与本地云存储的部署经验热词里有人提到视频本地云存储架构这个场景挺有意思我也踩过一些坑值得单独讲一讲。视频监控的存储有几个显著特点写多读少、数据量大、对实时性有要求、对成本极其敏感。一套摄像头数量上百的监控系统每天产生的数据量就有好几个TB。如果全量存云端带宽和流量费用直接能把预算吃穿。所以现在的主流方案是本地存储云端归档的混合架构。本地部署一台NVR或者NAS负责实时写入和最近一段时间的录像保存比如保留最近7天或者30天。超过这个周期的录像通过业务低峰时段比如凌晨定时上传到对象存储或云端冷存储归档。这样既保证了实时录像写入的高带宽和低延迟又把长期存储的成本压了下来。视频存储场景还有一个常被忽略的问题是文件碎片化。摄像头推流如果是按时间片写文件每个文件几秒钟到几分钟不等一天下来会产生成千上万个小文件。小文件多会导致文件系统元数据膨胀、读写效率下降、备份速度变慢。我的建议是写入端尽量做聚合把若干时间片合并成更大的文件段或者直接用对象存储接收录像流对象存储对小文件的支持远好于传统文件系统。3.4 分布式事务与定时任务的存储侧解法微服务和分布式架构普及之后分布式事务成了绕不开的话题。业务跨多个服务、多个数据库传统的本地事务没法保证跨库的原子性这时候就要在存储之上做文章。常见的方案有两阶段提交、最终一致性和事务消息。两阶段提交在这个场景下比较重性能和可用性都有牺牲实际生产环境用得不算多。最终一致性是主流思路核心是本地消息表或事务消息加定期对账。举个例子订单服务在本地数据库写入订单数据的同时写入一条消息记录到消息表然后再异步把消息发送出去。下游服务消费消息后执行自己的业务执行成功了就回执确认。如果中途出错了上游通过定时任务扫描消息表把还没确认的消息重新发送直到下游处理成功。这个方案实现简单、性能开销小也是绝大多数公司的选择。定时任务本身也有存储侧的讲究。分布式架构下定时任务不能每个人都去自己的本地调度否则同一个任务会被多个节点重复执行。常见的解法是用分布式任务调度框架比如XXL-Job、ElasticJob它的注册中心和数据存储需要一套高可用的数据库来记录任务元数据、调度日志和执行结果。任务调度的存储设计上要注意任务执行记录、调度锁这些关键数据的可靠性和并发安全。我见过有人在调度中心里用MySQL存任务日志结果日志量大导致表膨胀最后把调度中心拖垮了。合理的做法是任务日志定期清理或归档到对象存储调度中心只保留最近几天的数据。4. 常见问题与排查技巧实录4.1 如何快速判断当前系统用的是什么存储接到一个陌生系统第一步先搞清楚它底下用的是什么存储这个排查能力非常实用。最简单的办法是看主机上的挂载信息。Linux系统里执行df -hT可以查看所有挂载点的类型。如果是ext4、xfs这类文件系统至少是文件存储或块存储上面做了文件系统如果挂载点是类似s3://bucket的形式那就是对象存储的挂载工具比如s3fs、goofys如果是NFS挂载mount命令里会带nfs类型。Windows下可以通过“磁盘管理”和“文件共享”查看本地磁盘和网络驱动器。再进一步看数据库的部署方式。如果数据库目录在一个数据盘上底层多半是块存储如果数据库跑在容器里看StorageClass和PV/PVC的定义能从StorageClass的provisioner判断底层是云盘还是分布式存储。还有一个小技巧看系统里有没有安装存储厂商的Agent比如华为、深信服、Dell EMC都有各自的存储管理客户端看到了基本就能确认。这些判断方法都不难难的是一开始有排查意识。很多系统问题表面看是程序bug数据库慢追根溯源其实都发生在存储层。先把存储形态摸清楚排查路径才不会走偏。4.2 存储性能问题的排查思路存储出问题最典型的症状是系统变慢、IO等待升高、数据库查询卡顿。我总结了几个排查步骤按照顺序做基本能定位到问题。第一步看系统负载和IO状态。top命令里看waIO等待占比iostat -x 1看每个磁盘的%util、await、svctm这些指标。如果%util长期超过80%磁盘基本就是瓶颈了。这里要注意%util高不代表一定是硬件坏了也可能是文件系统碎片化、或上层的排队模型不合理导致的需要结合await和队列长度综合判断。第二步看存储协议层。如果是NFS或云盘挂载还要检查网络延迟和重传率。NFS经常出现的问题是客户端和服务端的版本不匹配、或者网卡MTU设置不一致导致性能波动很大。云盘的性能还受底层多租户的影响有时候IO延迟突然飙高是同一块物理存储上其他租户在吵闹邻居。第三步才是排查业务层面。比如SQL是不是走了全表扫描、有没有合理的索引、是不是一次查询拉取的数据量过大。存储优化和SQL优化往往是相辅相成的两边都要看。有个让我印象深刻的案例某系统每天都有一段时间响应缓慢排查存储、网络都没发现问题最后追到是定时备份任务在高峰期跑占用了大量IO。这就是典型的容量规划和运维窗口设置问题。备份、归档、大数据分析这类重IO任务尽量错峰执行能省掉非常多的幺蛾子。4.3 存储架构选型中的几条实用建议最后聊一些在项目实践中总结下来的选型经验都是真金白银换来的教训。第一条建议不要盲目追新。看到别人用了什么新技术就觉得自己的老架构不行这种心态特别危险。判断一个技术方案是否合适要看数据量级、并发量、团队维护能力而不是看技术热不热门。我之前见过一个团队为了上分布式而把好好的单体存储架构推倒重来结果过了半年又迁回去了。选型的核心是解决实际问题不是赶时髦。第二条建议数据分层比数据单一存储更常见。大部分业务场景其实是热数据 温数据 冷数据的混合模式。全部数据放一种存储里要么是成本过高要么是性能浪费。热数据放缓存或高性能块存储温数据放SSD冷数据放到低成本的对象存储。分层之后成本能降一个数量级这是最实际的省钱方式。第三条建议容量规划要留余量但要相对克制。存储扩容不像应用发布可以随时来需要提前规划。但也不用一上来就买一大堆容量因为存储硬件贬值和降价很快。我的习惯是当前使用率超过60%就开始准备扩容流程超过70%就必须完成扩容。这样既不会因为多用浪费成本也不会因为突发的数据增长而手忙脚乱。第四条建议备份和容灾一定要从第一天就想清楚不要等出事了再补。很多事故复盘到最后都是数据没了才发现备份是坏的或者有备份但恢复时间太长。备份的关键不是做了没而是能不能恢复恢复演练要定期做这个习惯一定要有。5. 写在最后一点个人体会数据存储这个领域表面上是在跟磁盘、协议、代码打交道本质上是在跟风险和成本做博弈。数据丢不丢、系统快不快、扩容顺不顺、费用高不高每一项决策都是在各种约束之间找平衡点。我个人的体会是存储方向的核心能力不是背概念、记参数而是理解每一层技术之间的依赖关系以及它们在不同业务场景下的取舍逻辑。遇到问题的时候能一层一层拆下去——从应用层到文件系统、再到存储介质和网络链路——这种排查能力才是真正值钱的地方。如果你正准备踏入这个领域我建议不要一上来就啃大部头的存储架构书。先在自己手边的小项目里把一个简单的数据库搞明白数据文件落在哪里、哪些参数影响性能、备份与恢复怎么做。把一条链路吃透再逐步往外扩展比咋咋呼呼读一堆文章有用得多。存储这个方向看起来抽象实际上门槛并没有想象中那么高。只要肯动手、多折腾、存得住性子去啃那些慢问题你迟早也能把这个领域看得明明白白。
阅读完成 · 觉得有帮助?