1.2 自建存储 vs COS:一笔账算清
场景:一台闲置服务器引发的幻想
拆完需求,第一股冲动就是自建。手里正好有台 4 核 8G 的闲置云服务器,挂块硬盘每月也不过几百块。我拿出计算器一按,1TB 硬盘几个月就能买断,COS 一年下来还要交存储费,这不明摆着自建便宜吗?这种买断思维特别有说服力,因为它只算看得见的钱,而钱一旦以每月多少的形式出现,人就会觉得它免费。
这个念头持续了大概两天,就被三件事打碎:一是带宽,云服务器默认只有很小的公网带宽,下个 500MB 的文件要等一个多小时,团队五个人根本没法用;二是容量,1TB 听着多,设计稿和视频塞起来很快,半年就满,扩容等于换机器迁移数据,还得停机一夜;三是可靠性,单机一块盘,坏了全完,多年的设计稿跟着陪葬。自建存储的钱不在硬件上,都在带宽、冗余和运维的暗处,而这些钱按月递增,永远不会停止。我后来把这套心理活动讲给朋友听,发现每个亲手搭过存储的人都有同一段心路:先是觉得自己买硬件赚了,然后被带宽教做人,最后在某个深夜的故障后彻底想通。
方案:两条路的对账单
我把两条路的开销摊在一张表里,按团队真实用量(约 500GB 存储、月下载 200GB、50 人使用)估算。为了公平,自建那一列我按四年折旧、含人工的方式算,不刻意夸大:
| 对比项 | 自建存储 | 对象存储 COS |
|---|---|---|
| 首期投入 | 服务器加硬盘约 4000 元 | 0 元,按量付费 |
| 带宽 | 需升级到 20Mbps,月费 800 元起 | 按流量计费,或走 CDN 更便宜 |
| 扩容 | 换机器、迁移数据,停机一夜 | 控制台改配置,无感扩容 |
| 可靠性 | 单机约 99%,看运气 | 服务协议 99.99% 起步,多副本 |
| 运维 | 我自己,半夜报警自己起 | 云厂商兜底,我只管调用 |
| 技术栈 | 要写存储层、备份脚本、监控 | 写配置和调用,代码量极小 |
再看一笔一年的明细账,把每一项钱都摆到桌面上。注意自建的带宽是固定开销,用不用都要交,而云上不用就不花钱:
| 费用项 | 自建(元/年) | COS(元/年) |
|---|---|---|
| 硬件折旧 | 6000 | 0 |
| 带宽 | 9600 | 0(走 CDN 回源计费) |
| CDN 加速 | 不适用 | 约 1800 |
| 存储费 | 0(已买断) | 约 1200 |
| 备份与冗余 | 约 2000(第二块盘) | 0(多副本已含) |
| 运维工时 | 无法估,按一次故障两天算 | 0 |
| 合计 | 17600 起 | 约 3000 |
账算到这份上,还要补一个决策维度:什么情况下我会真的选自建?我也认真想过这个问题:
| 场景 | 更优选择 | 理由 |
|---|---|---|
| 个人小站、几 GB 文件 | 自建无妨 | 带宽够用,宕机无后果 |
| 团队协作、持续增长 | 对象存储 | 扩容和可靠性是刚需 |
| 内网隔离、合规要求 | 自建或私有化 | 数据不能出门 |
| 突发大流量下载 | 云上按量 | 固定带宽扛不住峰值 |
结论很明显:自建的便宜是幻觉,省下的是明面的存储费,交出去的是带宽、冗余和半夜的睡眠。买断的硬件只会贬值,而云存储的单价年年都在降。算账时别忘了把新客优惠算进去,可以先看一眼 腾讯云产品特惠,存储包和流量包的新客价往往比官网列表低不少,第一年成本还能再降一截。
配置:让存储后端随时可切换
虽说选了 COS,我还是在后端留了一层抽象,方便哪天想换回自建或迁移到别的云。Go 里这事不复杂,定义接口即可,实现细节关门之后随便换。这一层后来证明是整个后端最值钱的设计之一:
// Store 定义存储后端的最小行为,和具体厂商解耦
type Store interface {
// 生成上传地址与凭证
SignedUpload(ctx context.Context, key string, size int64) (*Upload, error)
// 生成带签名的下载地址
SignedDownload(ctx context.Context, key string, ttl time.Duration) (string, error)
// 检查对象是否存在(秒传与对账用)
Head(ctx context.Context, key string) (int64, error)
}
// CosStore 实现 Store,内部封装 COS SDK
type CosStore struct{ client *cos.Client }
// Upload 是返回给客户端的直传凭证
type Upload struct {
URL string // 客户端直传的目标地址
Token string // 临时密钥信息
Expire time.Duration // 有效期
}
上线半年后这层抽象真的救了我一次:某区域 COS 抖动,上传成功率掉到一半以下,我把配置切到另一个桶,只改了初始化代码,接口不变,调用方零感知。如果当初把 COS SDK 的调用散落在 handler 各处,这次切换至少要改两天,而且必然漏改。平时写代码时,要求所有和 COS 打交道的代码都必须经过 Store 接口,单元测试里注入一个 LocalStore 实现,走本地目录,CI 里跑完整流程不花一分钱云上费用。这个习惯让重构变成一件安全的事。
踩坑:账单里那些看不见的角落
第一是请求费用。COS 除了存储费和流量费,还有按请求次数计费的一项,删文件、列目录、分片上传的每一次接口调用都算钱。我们早期分片设得太小,1GB 文件切了上千片,初始化、上传、完成各一次请求,光请求费就比流量费还高,详尽的分片策略在 2.3 大文件分片一节。分片大小和请求次数之间有个甜蜜点,值得上线后盯一周账单反复调。
第二是存储类型错配。为省钱我把桶里所有文件设成了低频存储,结果频繁读取的文件每次下载都有额外取回费,算下来比标准存储还贵。存哪类文件用哪类存储,得看访问频率,不能一刀切,热数据用标准存储,冷数据才归档,这部分在 5.2 生命周期一节展开。
第三是欠费停服。小项目没有财务提醒,某天流量突增把余额刷掉,桶直接被停,整个网盘 404,所有用户同时来找我。后来我在云监控里配了余额告警,余额低于阈值就发通知,还会同时发给团队群,这一招在 5.3 监控告警里细讲。
第四是 NAT 网关费。有人传文件传到一半去查账单,发现费用蹭蹭涨,原因是早期测试时把回源地址配错了,所有下载都在绕远路,流量费按最贵的路径计。配置类的东西改一行就是钱,上线前必须逐项核对费用路径。
第五是出口流量费的方向感。云上的流量费分上传和下载两个方向,上传进对象存储通常免费,下载才收费,而 CDN 回源到 COS 的那一段也要单独算。有一阵子我搞不清三段费用谁收谁,优化了半天成本反而涨了,搞得啼笑皆非。后来我把整条链路的费用画成一张流向图贴在墙上,每次调配置前先看一眼图,再没犯过方向错误。
最后补一段给纠结者的心里话。我见过很多团队在自建与上云之间摇摆半年,服务器买了又退,方案写了又废,最后什么都没上线。其实选哪条路都不致命,致命的是一直选。先用最糙的方式跑起来,让真实用户和真实账单替你做决定,这比任何 PPT 里的对比表都管用。我们的需求表和对账单都还挂在 wiki 上,每次新人加入都会被这篇文档拦下问一堆问题,回答完这些问题,他就理解了这个系统为什么是今天这个样子。
自建方案还有一笔账容易漏算:硬件折旧后的迁移。硬盘三年必换、服务器五年淘汰,换新又是一轮采购加停机窗口。云端按月付费永远用新硬件,这笔隐性成本加进去,自建的价格优势进一步缩水。
我们的结论不是自建一定差,而是小团队的时间不该花在造存储轮子上。如果公司有专门的运维团队与机房资源,结论可能不同。技术选型永远因地制宜,但算账的方法是相通的。
小结
自建还是上云,本质是买断还是租用。租到的是带宽、可靠性和运维时间,买断的是贬值资产。对我这种五人小团队来说答案没有悬念:把存储交给 COS,把人力省下来写业务。这笔账算清之后,后面所有技术选型都没再纠结过,因为争论的终点永远是一张对账表,而不是谁嗓门大。如果你正处在选型的当口,我建议你也花一小时把这张表填出来——填表的过程会逼你直面自己到底有多少用户、多少流量、多少运维时间,很多自我感动式的技术情怀在数字面前会自动消失。最后提醒一句,表格里的数字不必精确到个位,量级对了结论就对,过度精确反而让决策拖延,先用粗估上线,有了真实账单再回来修这张表,5.4 成本复盘一节就是修过三轮之后的结果。
