十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

块存储、文件存储与对象存储:核心原理、场景选择与实战避坑指南

块存储、文件存储与对象存储:核心原理、场景选择与实战避坑指南 1. 存储江湖三剑客从“存什么”到“怎么存”如果你是一名后端开发者或者正在搭建自己的应用那么“存储”这个词对你来说一定不陌生。但当你面对“块存储”、“文件存储”、“对象存储”这三个选项时是不是感觉有点懵它们听起来都像是用来存东西的但具体有什么区别又该在什么场景下用哪个呢这就像去五金店买工具螺丝刀、扳手、锤子都能“干活”但拧螺丝、拧螺母、敲钉子用错了工具不仅费劲还可能把活儿干砸了。今天我们不谈那些晦涩的协议标准就从你最熟悉的日常开发场景出发掰开揉碎了聊聊这存储界的“三剑客”。你会发现理解它们的关键不在于记住那些复杂的定义而在于想清楚两个最根本的问题你的数据长什么样以及你打算怎么用它弄明白了这两点选型就成功了一大半。无论是处理数据库文件、用户上传的图片还是海量的日志你都能立刻找到最趁手的那把“工具”。2. 块存储给服务器挂载的“超级硬盘”想象一下你有一台云服务器ECS它的系统盘只有40G现在你需要部署一个MySQL数据库。数据库文件会持续增长40G显然不够用。这时候你最直接的想法就是“给这台服务器再加一块硬盘”。而块存储扮演的就是这块“云硬盘”的角色。2.1 核心原理最底层的“磁盘扇区”块存储的本质是提供了一块原始的、未格式化的存储空间。它对上层操作系统比如Linux来说就像一块物理硬盘。这块“云硬盘”被划分成一个个固定大小的“块”Block通常是512字节或4KB每个块都有一个唯一的地址。操作系统通过SCSI、iSCSI、光纤通道等协议以“读写第XXX号块”这样的指令来操作它。关键点在于块存储本身不关心你存的是什么。它不知道你存的是数据库文件、系统日志还是一个电影文件。它只负责准确、高效地读写指定地址的块。因此格式化文件系统如EXT4、XFS、NTFS并挂载到目录是使用块存储的必要步骤。挂载后对你而言它就是一个普通的目录如/data所有文件操作都由操作系统的文件系统模块来管理。2.2 典型应用场景与实操场景一数据库这是块存储的“主场”。像MySQL、Oracle、PostgreSQL这类关系型数据库其性能极度依赖磁盘的IOPS每秒读写次数和低延迟。块存储能提供稳定的高性能和毫秒级的延迟并且支持像“快照”这样的功能可以在瞬间为整个磁盘创建数据副本用于备份或快速克隆测试环境。场景二需要直接读写磁盘的应用某些高性能计算HPC、大型企业级应用如SAP或者需要直接访问裸设备的场景块存储是唯一选择。因为它们需要绕过文件系统直接控制磁盘块以获得极致性能。实操心得性能与成本权衡在云平台上购买块存储时通常会面临性能类型的选择如通用型SSD、高效云盘、ESSD云盘。这里有个经验不要只看容量和价格更要关注IOPS和吞吐量指标。一个500G的高性能ESSD云盘价格可能远超1T的普通云盘但对于数据库而言前者的价值巨大。如果预算有限可以考虑将数据库的日志文件如MySQL的binlog、redo log放在高性能盘上而数据文件放在容量型盘上这是一种常见的性价比优化策略。注意块存储通常与特定服务器实例强绑定。虽然云盘可以卸载并挂载到另一台服务器但在同一时刻一块云盘只能被一台服务器挂载。这意味着它不适合需要被多台服务器同时访问的场景。3. 文件存储网络共享的“文件柜”现在场景变了。你有一个小团队开发、测试、运维人员需要共同访问同一套项目文档、配置文件或者共享的软件安装包。如果给每个人的电脑都复制一份不仅浪费空间同步起来更是噩梦。这时你需要一个像公司里的“公共文件服务器”一样的东西——这就是文件存储。3.1 核心原理基于协议的文件级共享文件存储是在块存储之上构建了一个带有目录树结构的文件系统并通过标准的网络文件协议如NFS、SMB/CIFS共享出来。它的核心是“文件”和“目录”这两个概念。当你的服务器或PC通过NFS协议挂载了一个文件存储服务后访问远程的/shared/project/config.yaml就像访问本地文件/mnt/nfs/config.yaml一样。所有文件创建、删除、读写、权限管理的操作都通过文件协议在网络上完成。文件存储服务端负责维护统一的目录结构和文件元数据如文件名、大小、修改时间、权限。3.2 典型应用场景与实操场景一企业内容管理与协作这正是开头的例子。NAS网络附加存储是文件存储的硬件形态而云上的文件存储服务如阿里云NAS、AWS EFS是其云化版本。非常适合存放办公文档、设计稿、视频素材等需要多人协作编辑的文件。场景二应用共享存储在Web服务器集群中经常需要保证所有服务器上的网站代码、用户上传的静态文件如图片、CSS是一致的。通过文件存储可以将/var/www/html目录挂载到多台Web服务器上实现代码和文件的统一管理无需在每台服务器上同步。场景三容器持久化存储在Kubernetes中有状态应用如WordPress需要持久化存储。通过创建PVC持久卷声明并关联到文件存储类型的PV持久卷Pod可以在不同的节点间漂移但始终能访问到同一份数据。实操踩坑性能与协议选择文件存储的性能受网络延迟和协议开销影响通常不如直接访问本地块存储。一个常见的坑是大量小文件的随机读写场景。如果你在文件存储上运行一个包含数十万个小文件的Git仓库操作性能可能会急剧下降。此时需要评估是否真的需要共享访问如果不需要改用本地SSD可能是更好的选择。另外NFS协议主要有v3和v4两个版本。v4在锁机制、安全性、跨防火墙支持上更好但兼容性可能略逊于v3。在云环境通常使用服务商推荐的版本即可。4. 对象存储面向互联网的海量“仓库”最后我们来到当下最火热、也最容易与文件存储混淆的领域——对象存储。假设你正在开发一个社交App用户会上传海量的照片和短视频。这些数据有几个特点数量巨大海量、单个文件大小不一从几KB到几个GB、读多写少、需要通过网页或App直接访问。用文件存储来存目录可能会被撑爆管理困难。用块存储无法直接通过HTTP访问。这时对象存储如阿里云OSS、AWS S3、腾讯云COS就是为这种场景而生的。4.1 核心原理扁平化结构与RESTful API对象存储彻底抛弃了传统的目录树结构。它采用一种扁平化的“桶-对象”两层模型。桶Bucket相当于一个命名空间或顶级容器通常按项目或应用来创建。对象Object存储的基本单元就是你的文件本身数据以及伴随它的元数据和全局唯一的键Key。这个“键”就是对象的地址看起来可能像images/2023/10/01/user_avatar_12345.jpg。虽然它包含斜杠看起来像路径但对对象存储服务来说这只是一个字符串标识符并不是真正的目录层级。这种设计让扩展性变得极其简单。访问对象存储几乎全部通过HTTP/HTTPS RESTful API进行。上传一个文件就是一次PUT请求下载则是GET。这使得任何能联网的设备或程序都能轻松使用它也天然适合作为网站、App的静态资源图片、视频、前端JS/CSS托管源。4.2 典型应用场景与实操场景一静态网站与资源托管这是对象存储的“杀手级”应用。将你的前端项目HTML、CSS、JS、图片全部上传到OSS的一个桶里并开启“静态网站托管”功能再绑定一个自定义域名一个高可用、无限扩容、成本低廉的网站就上线了。结合CDN内容分发网络加速全球访问速度飞快。场景二海量用户生成内容UGC文章开头的“微信小程序拍照存储文件”就是一个典型例子。小程序端通过调用云开发SDK或直接调用OSS的PostObject API将用户拍摄的照片安全地上传到指定的桶中。后端无需再处理文件流只需存储文件的访问地址URL到数据库即可。场景三备份与归档凭借其极低的存储成本尤其是低频访问、归档存储类型对象存储是企业数据备份、日志归档、冷数据存储的理想目的地。你可以用工具将数据库备份文件、服务器日志定期上传到OSS进行长期保存。实操代码示例Spring Boot集成MinIOMinIO是一个开源、兼容S3协议的对象存储常用于搭建私有云存储。下面是一个极简的Spring Boot集成示例演示上传和下载。添加依赖(pom.xml)dependency groupIdio.minio/groupId artifactIdminio/artifactId version8.5.2/version /dependency配置MinIO客户端(application.yml)minio: endpoint: http://localhost:9000 # MinIO服务器地址 access-key: your-access-key secret-key: your-secret-key bucket-name: my-bucket配置类与工具类Configuration public class MinioConfig { Value(${minio.endpoint}) private String endpoint; Value(${minio.access-key}) private String accessKey; Value(${minio.secret-key}) private String secretKey; Bean public MinioClient minioClient() { return MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); } } Service Slf4j public class MinioService { Autowired private MinioClient minioClient; Value(${minio.bucket-name}) private String bucketName; /** * 上传文件 * param file 文件 * param objectName 对象名Key如 “avatars/user1.jpg” * return 文件访问URL */ public String uploadFile(MultipartFile file, String objectName) throws Exception { // 确保桶存在 boolean found minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); if (!found) { minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); } // 上传 minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) .object(objectName) .stream(file.getInputStream(), file.getSize(), -1) .contentType(file.getContentType()) .build()); // 生成访问URL这里生成的是有时效性的 return minioClient.getPresignedObjectUrl( GetPresignedObjectUrlArgs.builder() .method(Method.GET) .bucket(bucketName) .object(objectName) .expiry(7, TimeUnit.DAYS) // 7天有效 .build()); } /** * 下载文件 * param objectName 对象名 * param response HttpServletResponse */ public void downloadFile(String objectName, HttpServletResponse response) throws Exception { GetObjectResponse object minioClient.getObject( GetObjectArgs.builder() .bucket(bucketName) .object(objectName) .build()); // 设置响应头 response.setContentType(application/octet-stream); response.setHeader(Content-Disposition, attachment; filename\ objectName \); // 流式拷贝到响应输出流 StreamUtils.copy(object, response.getOutputStream()); object.close(); } }实操心得费用与性能优化使用对象存储要特别注意其按量付费的模式。费用通常由存储容量、请求次数、下行流量三部分组成。存储容量选择适合的存储类型。标准型用于频繁访问的热数据低频型用于偶尔访问如每月几次归档型用于几乎不访问的冷数据如合规备份价格依次降低但取回数据可能需要时间并产生费用。请求次数每次GET/PUT等API调用都算一次请求。对于高并发访问的图片务必在前面叠加CDN。CDN会缓存图片大部分请求由CDN节点响应大大减少回源到OSS的请求次数和流量既能提速又能省钱。下行流量数据被外部网络下载时产生。同样CDN缓存能有效减少这部分流量。5. 终极对决如何根据场景做选择了解了各自的特点后我们可以用一个表格来直观对比并在具体场景中做出选择。特性维度块存储 (Block Storage)文件存储 (File Storage)对象存储 (Object Storage)数据模型原始块设备需格式化文件与目录树对象数据元数据键扁平化访问协议SCSI, iSCSI, FCNFS, SMB/CIFSHTTP/HTTPS RESTful API (S3兼容)典型延迟毫秒级 (极低)毫秒到几十毫秒几十毫秒到几百毫秒性能特点高IOPS低延迟稳定受网络和协议影响适合顺序读写高吞吐适合大文件海量小文件性能需优化扩展性单设备容量有限纵向扩展容量可扩展但存在文件系统极限近乎无限横向扩展共享能力通常单点挂载某些集群文件系统除外支持多点并发读写协议级锁天生支持海量并发读取主要用途数据库、企业核心应用、需要直接磁盘访问的场景文件共享、NAS、容器持久化卷、HPC home目录静态网站、图片视频等UGC、备份归档、大数据分析源成本模型按预置容量和性能等级收费按实际使用容量和性能等级收费按存储量、请求次数、流出流量等多维度计费场景决策树你的数据需要被多台服务器同时读写吗是- 考虑文件存储如共享配置文件、代码仓库。否- 进入下一步。你的应用是否需要像访问本地硬盘一样进行低延迟、高IOPS的随机读写例如运行数据库是- 选择块存储。否- 进入下一步。你的数据主要是通过互联网浏览器、App被海量用户访问吗或者数据量极大需要极低的存储成本是-对象存储是最佳选择。否- 你可能需要重新审视需求或者文件存储依然是一个简单可靠的选择例如内部应用的简单文件共享。一个综合案例解析一个典型的电商网站架构可能会同时用到三者块存储用于承载MySQL数据库和Redis持久化提供事务处理所需的高性能磁盘IO。文件存储用于开发团队共享的代码仓库如Git以及作为应用服务器的共享日志目录方便日志收集。对象存储用于存储所有商品图片、用户头像、宣传视频并通过CDN加速分发。用户订单中的PDF电子发票也可以生成后存入对象存储进行归档。6. 常见误区与避坑指南在实际选型和迁移中我踩过不少坑这里分享几个最常见的误区误区一把对象存储当文件存储用进行频繁的列表和重命名操作。对象存储的ListObjects列出文件操作在海量对象下是昂贵且低效的因为它本质上是扫描一个扁平化的命名空间。而“重命名”操作在对象存储中是不存在的你需要先复制对象到新Key再删除旧对象成本很高。如果你的应用严重依赖目录遍历和文件重命名那么文件存储才是更合适的选择。误区二在块存储上搭建文件共享服务。我曾见过有团队为了“高性能”在云服务器上用块存储搭建了NFS服务供其他服务器挂载。这确实能工作但你需要自行解决高可用、备份、扩容等一系列问题运维复杂度陡增。而云厂商提供的文件存储服务是托管服务这些能力是开箱即用的。不要重复造轮子尤其是基础设施的轮子。误区三忽视对象存储的“最终一致性”模型。大多数对象存储为了保障高可用和分区容错性在数据更新PUT/DELETE后可能会有一个极短的时间窗口通常是毫秒级在这期间不同节点读到的数据可能不一致比如刚上传完图片立即访问可能返回404。对于绝大多数互联网应用这完全可以接受。但如果你正在构建一个金融交易系统要求强一致性的读写那么就需要仔细阅读云服务商的文档或考虑使用支持强一致的存储服务。避坑实操迁移文件到对象存储当你决定将应用中的文件如用户上传从服务器本地磁盘或文件存储迁移到对象存储时切忌“一刀切”直接改代码。一个稳妥的灰度方案是新上传的文件直接写入对象存储。代码中实现一个兼容层读取文件时先尝试从对象存储获取通过Key如果返回404Not Found则回退到原有的本地路径或文件存储路径去查找并读取同时可以异步地将这个老文件搬运到对象存储并更新数据库中的引用地址。待所有活跃文件都迁移完毕观察一段时间后再下线兼容层逻辑。这样能确保迁移过程平滑对用户无感知。
返回列表