技术分享|
上码团队
/2025-12-21/10 分钟

CAS 内容寻址存储:上码的核心技术

不是每次部署都该重新上传全部文件。本文用更具体的方式解释 CAS 在静态网站托管里的作用:为什么它能减少重复上传、让版本回退更干净,并帮助静态资源更稳定地分发。

CAS 内容寻址存储:上码的核心技术

很多静态网站托管平台表面上都在做同一件事:

  • 上传文件
  • 发布网站
  • 给你一个链接

但真正决定上传效率、版本管理和回滚体验的,往往不是页面上那个“上传”按钮,而是底层怎么存文件。

上码采用的是 CAS(Content-Addressable Storage,内容寻址存储) 这条思路。它的价值不在于“名字听起来很技术”,而在于它能解决传统静态发布里几个很常见的问题:

  • 每次都要重传一堆没变过的文件
  • 发布后新旧文件容易混
  • 回滚时还得重新找旧包
  • 静态资源难以放心做强缓存

什么是 CAS

先把概念讲清楚。

CAS 的核心不是“按文件名存东西”,而是按文件内容存东西

也就是说,一个文件真正的身份不是:

  • app.js
  • logo.png
  • index.html

而是它的内容哈希。

在上码当前的实现里,文件会按内容计算 SHA-256。只要内容完全一样,它的哈希就一样;只要内容变了,哪怕只改了一个字符,哈希也会变。

这意味着:

  • 同样内容的文件不需要重复存很多份
  • 文件一旦写入,就可以当成不可变对象处理
  • “路径”和“内容”可以被拆开管理

传统静态上传为什么容易浪费

假设你的网站有 120 个文件:

  • 1 个 HTML
  • 8 个 CSS / JS
  • 100 多张图片和字体

你只改了首页一段文案和一张 banner 图。

如果平台按“整个目录重新传一遍”的方式工作,那你很可能还得重新上传大量其实没变的文件。

这类浪费不只发生在上传时间上,还会影响:

  • 带宽消耗
  • 发布等待时间
  • 回源压力
  • 用户拿到新版本的稳定性

对经常更新活动页、作品集、营销站、文档站的人来说,这种低效会很快变成体验问题。

CAS 在上码里是怎么工作的

以上码当前的静态托管链路为例,发布过程可以简化成三步理解。

1. 浏览器先算每个文件的哈希

你上传文件之后,前端不会立刻把所有文件原样推上去,而是会先对每个文件计算 SHA-256。

这一步的意义是:平台先知道“你这次想发的到底是什么内容”,而不是盲目接收一堆同名文件。

2. 服务端只要求上传缺失对象

前端把这次部署的文件清单发给服务端后,服务端会检查:

  • 哪些哈希对应的对象已经存在
  • 哪些对象是这次真正缺的

如果某个文件内容以前已经传过,即使它今天挂在另一个项目、另一个版本、另一个路径下,它也不需要重新上传。

这就是 CAS 真正带来的“去重”。

3. 最终版本由 manifest 组织起来

对象池里只存“内容”,但用户访问网站时需要的是“路径”。

所以每次部署完成后,还需要一份 manifest 去描述:

{
  "index.html": { "hash": "sha256-abc...", "size": 1234 },
  "assets/app.js": { "hash": "sha256-def...", "size": 5678 }
}

这份 manifest 的作用不是存内容,而是告诉分发层:

  • 这个版本下
  • 哪个路径
  • 应该指向哪个对象

为什么这对静态网站特别有用

1. 只传真正变化的文件

这是最直观的好处。

如果你只改了一张图和一个 CSS 文件,那就没有必要把整站重新传一遍。

对小站来说,这意味着等待更短;对大站来说,这意味着发布链路更稳。

2. 文件一旦写入,就更适合做强缓存

因为对象是按内容哈希存的,只要哈希不变,内容就不变。

这时平台就可以更放心地给对象配置:

  • 长缓存时间
  • immutable 响应头

这样 CDN 和浏览器就更容易把静态资源缓存住,而不会担心“同一个 URL 背后内容偷偷变了”。

3. 新版本和旧版本不会天然互相覆盖

这点很关键。

因为路径和内容是通过 manifest 关联的,所以旧版本并不会因为新版本上线而直接被“写没”。

只要旧版本对应的 manifest 还在,旧版本就仍然是一个完整版本,而不是一堆被覆盖过的残片。

4. 回滚更干净

如果你想更深入看这一点,可以结合这篇:网站更新翻车了怎么办?静态网站版本回滚的最短路径

CAS 对回滚最大的帮助在于:

  • 旧对象还在
  • 旧 manifest 也还在
  • 回滚时不需要重新打一个旧包再上传

这会让回滚动作更接近“切回旧版本指针”,而不是“重新来一遍发布”。

上码当前的存储结构大致是什么样

简化理解,可以看成两层:

R2 Bucket/
├── objects/
│   ├── sha256-abc...
│   └── sha256-def...
└── manifests/
    └── <projectId>/
        └── <deploymentId>.json

这里最重要的区别是:

  • objects/ 存的是不可变内容对象
  • manifests/ 存的是某次部署版本的路径映射

也就是说,用户访问的是“版本视角”,底层存储的是“内容视角”。

一个更容易理解的例子

假设你的网站里有这些文件:

  • index.html
  • app.css
  • hero.png

第一次部署时,三者都会进入对象池,并生成版本 A 的 manifest。

第二次部署时,你只修改了 app.css

这时系统不需要重新上传:

  • index.html
  • hero.png

只需要上传新版本的 app.css,再生成版本 B 的 manifest。

结果就是:

  • 对象池只新增了真正变化的内容
  • 版本 A 和版本 B 都仍然清楚可辨
  • 回退时可以明确回到旧版本

CAS 不是“更快上传”这么简单

很多人第一次听到 CAS,只会把它理解成“秒传”。

这当然是结果之一,但不是全部。

更大的价值其实在于三件事:

1. 发布链路更稳定

因为你减少了不必要的重传,也减少了发布时新旧文件混杂的机会。

2. 分发更容易和缓存策略配合

不可变对象和强缓存天生更搭。

3. 版本管理天然更清晰

当每一次部署都有自己的 manifest,版本这件事就不再依赖“记住当时传了什么文件”。

对使用者来说,最重要的感知是什么

如果你不是在看架构图,而是在真的发网站,你能感受到的变化通常是:

  • 第二次、第三次发布更快
  • 改一点内容,不用等整站重传
  • 资源缓存更稳
  • 版本回退更自然

这也是为什么 CAS 特别适合:

  • 活动页
  • 作品集
  • 营销站
  • 文档站
  • AI 生成网页上线后的持续修改

最后的建议

静态托管平台看起来都在做“上传文件”,但底层怎么存,决定了你后面会不会频繁被这些问题绊住:

  • 发布慢
  • 版本乱
  • 回滚重
  • 缓存不稳

CAS 的价值,不在于它是一个很“高级”的技术名词,而在于它把静态网站发布这件事拆得更合理:

  • 内容按内容存
  • 版本按版本管
  • 路径通过 manifest 组织

对最终用户来说,这意味着更快的发布、更干净的版本管理,以及更稳的静态资源分发。

#CAS#架构#技术

准备好发布你的网站了吗?

上码提供极速、安全、易用的静态网站托管服务。无需运维,专注于你的创作。

免费开始部署