【免费下载链接】cachey
Read-through cache for object storage
Cachey 是一个面向 S3 兼容对象存储的高性能读穿透(read-through)缓存服务,核心入口是/fetchHTTP 接口。本文作为Cachey API 参考,逐项解析/fetch请求中精确的Range写法,以及C0-Bucket、C0-Config、C0-Object-Size、C0-Exact四个自定义请求头的用途与常见错误码,帮助你在部署 Cachey 对象存储缓存时一次写对请求。
Cachey 在架构中的位置
Cachey 工作在客户端与 S3 之间:
- 命中缓存:直接从内存/磁盘返回数据,不触碰后端
- 未命中:向 S3 下载,回填混合缓存(foyer 内存 + 磁盘),再返回
- 固定 16 MiB 页大小:请求的字节范围会被映射到页对齐的缓存条目上(定义见 src/service/mod.rs 的
PAGE_SIZE与pagerange) - 支持多桶副本:选择、回退、对冲下载都由服务端自动管理
💡 设计前提:缓存的是不可变(immutable)对象,因此读多写少的 blob 场景收益最大。
/fetch 请求格式总览
HEAD|GET /fetch/{kind}/{object} Range: bytes=1048576-18874367路径中两个参数共同构成缓存键:
| 参数 | 含义 | 约束 |
|---|---|---|
kind | 桶集合标识(bucket set) | 1–64 字符,不含控制字符 |
object | S3 对象键(object key) | 1–1024 字符 |
请求头一览:
| 请求头 | 必填 | 作用 |
|---|---|---|
Range | ✅ | 指定精确字节范围 |
C0-Bucket | ❌ | 声明对象所在的一个或多个桶 |
C0-Config | ❌ | 按请求覆盖 S3 超时/重试配置 |
C0-Object-Size | ❌ | 声明对象总字节数 |
C0-Exact | ❌ | true时按精确范围缓存(≤16 MiB) |
路由注册与参数解析在 src/service/routes.rs 的fetch处理器中完成。
Range 请求头:如何写才"精确"
Range是/fetch唯一的必填请求头,必须写成单段形式:
Range: bytes={first}-{last}解析逻辑在 ReadRange 提取器 中,规则如下:
- 必须是单段范围:
bytes=0-99,200-299这种多段写法会返回416 - 首尾必须都是具体下标:
first <= last,且last < 2^40(约 1 TiB,由 16 MiB × 65536 页决定) - 省略
Range:直接400("Range header is required") - 结合
C0-Object-Size时,若范围起点 ≥ 对象大小,服务端不访问任何桶直接返回416
服务端会把你的范围映射到 16 MiB 的页上:比如请求1048576-18874367,实际会取第 0、1 页(0-16777215、16777216-33554431)再裁出你要的切片。响应中的Content-Range反映的是实际服务的范围,而缓存的仍是整页。
C0-Bucket:多桶副本的声明方式
C0-Bucket用于告诉 Cachey 对象存放在哪些桶里,行为规则:
- 可以发多个同名头:多个头表示冗余副本桶,第一个是首选桶,享有本地性偏好
- 省略时:
kind路径段会被当作唯一的桶名 - 桶名约束:1–64 字符、不含控制字符(见 BucketName)
示例:
GET /fetch/prod-videos/movie-2024.mp4 HTTP/1.1 C0-Bucket: us-west-videos C0-Bucket: us-east-videos-backup首选桶慢或失败时,服务端会依据健康度与延迟模型自动回退到其余桶,并可在下载时限内发起最多 3 份对冲副本(hedged requests)以压低尾部延迟——完整的选择、回退与对冲策略见 docs/replica-reads.md。
C0-Config:按请求微调 S3 超时与重试
C0-Config是空格分隔的键值对,用于在缓存未命中时覆盖本次 S3 请求的 SDK 配置(解析实现见 routes.rs,字段定义在 src/object_store/config.rs):
| 键 | 单位 | 含义 |
|---|---|---|
ct | ms | 连接超时(新建连接时生效) |
rt | ms | 读超时(首字节时间 time-to-first-byte) |
ot | ms | 操作超时(跨重试累计) |
oat | ms | 单次尝试超时 |
ma | 次 | 每个桶主操作的 SDK 最大尝试次数 |
ib | ms | 重试初始退避时长 |
mb | ms | 重试最大退避时长 |
fps | bool | 强制 path-style 寻址 |
例如:
C0-Config: ct=1000 oat=1500 ma=5 ib=10 mb=100三个实用要点:
- 未写的键保持默认:
C0-Config: ct=1000只覆盖连接超时,其余继承服务端配置 - 未知键会被忽略:写错键名不会报错(宽容解析),但缺少
=、数值非法、fps=1这类非法布尔会返回400 - 有上限:所有 SDK 超时最终受服务端下载时限约束(默认
--bucket-timeout-ms 5000、--download-timeout-ms 10000),且早期对冲副本只允许 1 次 SDK 尝试
C0-Object-Size 与 C0-Exact:两个进阶头
C0-Object-Size:声明对象总大小
告诉 Cachey 对象的精确字节数后,服务端能:
- 小对象的整页按实际剩余大小计入准入与延迟模型(虽然仍请求整页)
- 范围起点超过对象大小时本地判定 416,不浪费一次桶调用
- 若桶返回的实际大小不一致,返回
409(大小冲突);范围越过对象真实末尾则返回416
⚠️ 注意:准入信任你声明的大小。若声明偏小,该次读取实际可能持有超过预留的内存额度。
C0-Exact:精确范围缓存模式
默认模式下,即使只读 1 KiB,缓存的也是它所在的 16 MiB 页。如果对象的某些范围总是被完整读取(例如固定切片的热数据),可设置:
C0-Exact: true此时请求范围被整体下载并作为一个独立条目缓存:
- 上限 16 MiB,超出返回
400("Exact range exceeds the page size") - 只有请求完全相同范围的后续请求才会命中该条目
- 取值必须是字面量
true/false,1之类会400
选型建议:范围读会反复重叠 → 用默认页模式;范围固定且总是整段读 → 用C0-Exact省空间。
读响应:Content-Range 与 C0-Status
成功响应为206 Partial Content,响应头包含:
| 响应头 | 说明 |
|---|---|
Content-Range | 实际服务的字节范围,如bytes 1048576-18874367/52428800 |
Content-Length | 本次返回字节数 |
Last-Modified | 首个缓存条目的时间戳 |
Content-Type | 固定application/octet-stream |
C0-Status | 首个缓存条目的状态 |
C0-Status的格式为{first}-{last}; {bucket}; {cached_at},例如:
C0-Status: 1048576-16777215; us-west-videos; 1704067200- 前两项告诉你数据来自哪个桶、覆盖哪个字节范围
cached_at是 Unix 时间戳,0 表示本次是缓存未命中(刚下载)- 跨多页的 GET 响应中,后续各页的
C0-Status放在HTTP/2 trailers里;HTTP/1.1 只携带第一个条目
HEAD请求走同一解析逻辑,只返回头不返回体,适合探测对象是否存在及大小。
常见状态码速查表
| 状态码 | 含义 | 典型原因 |
|---|---|---|
400 | 请求无效 | 缺Range、C0-Config键值对格式错误、C0-Exact超限 |
404 | 对象不存在 | 所有桶都报NoSuchKey |
409 | 对象大小冲突 | 桶报告的大小与C0-Object-Size或已缓存值不一致 |
416 | 范围不可满足 | 请求越过对象末尾、多段范围 |
503 | 过载 | 准入失败或后端 429/503/SlowDown |
504 | 网关超时 | 桶下载超时(含回退后) |
错误到状态码的映射见 on_chunk_error。排查时优先看503是否伴随429——那说明 S3 侧在限流,可考虑调大ib/mb退避或降低并发。
顺带一提:监控接口
GET /stats:返回 10 秒窗口出入向吞吐的 JSON,适合负载均衡与健康检查GET /metrics:Prometheus 文本格式全量指标,含桶延迟模型、下载延迟、C0-Status相关统计
总结:一份请求头速记清单
- ✅
Range: bytes=first-last必填且必须是单段具体下标 - ✅
C0-Bucket可多值,第一桶为首选;不写则以kind为桶名 - ✅
C0-Config空格分隔键值对,只写要覆盖的项,超时受服务端总时限约束 - ✅
C0-Object-Size让边界判定提前本地化,但要保证数值真实 - ✅
C0-Exact: true用于固定热范围,上限 16 MiB - ✅ 想看每页缓存状态就启用 HTTP/2,读 trailers 里的后续
C0-Status
更多背景可参考项目文档:README.md、docs/replica-reads.md,以及副本选择的模拟实验 docs/simulation/README.md。
【免费下载链接】cachey
Read-through cache for object storage
相关推荐
VibeFigma API参考指南:Figma转React的 POST /v1/api/vibe-figma 请求参数与响应字段逐项精讲
VibeFigma API参考指南:Figma转React的 POST /v1/api/vibe figma 请求参数与响应字段逐项精讲 🎯 VibeFigm
SkiaSharp.HarfBuzz 2.88.1 API 变更深度解读:SKShaper.Result 新增 Width 属性与带宽度构造函数
SkiaSharp.HarfBuzz 2.88.1 API 变更深度解读:SKShaper.Result 新增 Width 属性与带宽度构造函数 本篇技术指南围
redux-localstorage persistState API完整参考:paths与config全解析
redux localstorage persistState API完整参考:paths与config全解析 redux localstorage 是一个轻量
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考