本文档展示了 cachex 库的全面性能基准测试结果,模拟了一个包含 10,000 个商品的真实电商商品搜索接口场景。
本基准测试展示的是冷启动(无预热)场景的性能表现。
- ✅ 无缓存预热:所有测试从空缓存开始,真实反映系统启动时的表现
- ✅ 冷启动零错误:在当前测试配置下,所有场景均实现零错误
- 🚀 预热后性能:如果缓存经过预热(命中率 99%+),吞吐量将显著提升,DB 负载将降至极低水平
💡 为什么冷启动很重要? 冷启动是系统最脆弱的时刻,也是最容易出现雪崩的时候。Cachex 通过 Singleflight + DoubleCheck 机制,配合合理的 TTL 配置,能够在冷启动时平稳运行。
- 平台: darwin/arm64
- CPU: Apple M3 Pro
- Go 版本: 1.23+
- 商品总数: 10,000
- 测试时长: 每场景 10 秒
- 数据库模拟: 基于 Semaphore 的连接池机制(真实模拟数据库连接池行为)
基准测试模拟真实的电商流量分布,遵循 帕累托法则(80/20 原则):
- 80% - 热门商品(前 50 个商品)
- 15% - 中等热度商品(第 51-500 个商品)
- 4% - 冷门商品(第 501-5,000 个商品)
- 1% - 不存在的商品请求
💡 这种分布反映了真实电商模式:少数商品获得大部分流量。
模拟高性能数据库,拥有大型连接池(100 连接),采用极致激进的缓存刷新策略,展示高负载下的性能表现。
配置:
DB 连接池: 100 (大型连接池)
DB 延迟: 90ms
Fetch 超时: 2s
数据新鲜 TTL: 1s (极致激进刷新)
数据过期 TTL: 24h (额外)
NotFound 新鲜 TTL: 500ms
NotFound 过期 TTL: 24h (额外)
并发数: 600
测试时长: 10s
结果 (冷启动):
总请求数: 5,049,890
成功: 4,999,371 (99.0%)
未找到: 50,519 (1.0%)
错误: 0 (0.0%)
总体 QPS: 504,989 req/s
缓存性能:
缓存命中率: 99.81%
数据库查询: 9,826 (0.2%)
DB QPS: 982.5 req/s
数据库拒绝: 0
DB 利用率: 88.4% (高负载)
吞吐量放大: 514.0x
延迟:
P50: 291ns
P95: 750ns
P99: 3.375µs
延迟分布:
<1ms 99.9% ████████████████████████████████████████████████
💡 关键洞察(冷启动):
- 99.81% 的缓存命中率,即使在 1 秒极致激进刷新策略下
- 505K QPS 极致吞吐量,600 并发下展现卓越性能
- 超低延迟:P50 仅 291ns,P99 为 3.3µs
- 88.4% DB 利用率:高负载运行,同时保留 11.6% 缓冲应对突发流量
- 982.5 DB QPS,吞吐量放大高达 514.0x
- 零错误冷启动:Singleflight + DoubleCheck 完美配合,高负载下仍保持零错误
- 预热后潜力:缓存预热后命中率可达 99.9%+,DB 负载将降至 1% 以下
模拟云数据库,中等连接池(20 连接),采用平衡的 TTL 配置。
配置:
DB 连接池: 20 (中等连接池)
DB 延迟: 85ms
Fetch 超时: 1s
数据新鲜 TTL: 5s
数据过期 TTL: 24h (额外)
NotFound 新鲜 TTL: 3s
NotFound 过期 TTL: 24h (额外)
并发数: 100
测试时长: 10s
结果 (冷启动):
总请求数: 552,220
成功: 546,698 (99.0%)
未找到: 5,522 (1.0%)
错误: 0 (0.0%)
总体 QPS: 55,222 req/s
缓存性能:
缓存命中率: 99.61%
数据库查询: 2,138 (0.4%)
DB QPS: 213.8 req/s
数据库拒绝: 0
DB 利用率: 90.9% (理想区间)
吞吐量放大: 235.0x
延迟:
P50: 833ns
P95: 5.25µs
P99: 12µs
延迟分布:
<1ms 99.7% ████████████████████████████████████████████████
💡 关键洞察(冷启动):
- 99.61% 的缓存命中率,5 秒平衡刷新策略
- 90.9% DB 利用率:接近最佳利用率,同时保留 9% 缓冲
- P50 延迟 833ns,P99 仅 12µs,延迟分布优秀
- 213.8 DB QPS,吞吐量放大 235.0x
- 零错误冷启动:测试中的连接池排队机制确保无请求被拒绝
- 预热后潜力:命中率可达 99.9%+,DB 利用率将降至 10% 以下
模拟共享数据库环境,小型连接池(13 连接),采用保守的 TTL 以减少负载。
配置:
DB 连接池: 13 (小型连接池)
DB 延迟: 125ms
Fetch 超时: 5s
数据新鲜 TTL: 10s
数据过期 TTL: 24h (额外)
NotFound 新鲜 TTL: 5s
NotFound 过期 TTL: 24h (额外)
并发数: 100
测试时长: 10s
结果 (冷启动):
总请求数: 73,060
成功: 72,330 (99.0%)
未找到: 730 (1.0%)
错误: 0 (0.0%)
总体 QPS: 7,306 req/s
缓存性能:
缓存命中率: 98.59%
数据库查询: 1,074 (1.4%)
DB QPS: 103.0 req/s
数据库拒绝: 0
DB 利用率: 99.0% (接近满载)
吞吐量放大: 70.2x
延迟:
P50: 791ns
P95: 5.833µs
P99: 831ms
延迟分布:
<1ms 98.6% ████████████████████████████████████████████████
<10ms 99.8% █
💡 关键洞察(冷启动):
- 98.59% 的缓存命中率,即使在 10 秒短刷新策略下
- 99.0% DB 利用率:接近满载,充分利用数据库连接池
- P99 延迟 831ms,受限于数据库连接池排队
- 103.0 DB QPS,吞吐量放大 70.2x
- 零错误冷启动:测试中的连接池排队机制确保无请求被拒绝
- 预热后潜力:命中率可达 99.9%+,DB 利用率将降至 20% 以下,延迟显著降低
模拟极度受限的数据库,极小连接池(8 连接),采用非常保守的缓存策略。
配置:
DB 连接池: 8 (极小连接池)
DB 延迟: 190ms
Fetch 超时: 10s
数据新鲜 TTL: 20s
数据过期 TTL: 24h (额外)
NotFound 新鲜 TTL: 10s
NotFound 过期 TTL: 24h (额外)
并发数: 100
测试时长: 10s
结果 (冷启动):
总请求数: 6,950
成功: 6,533 (94.0%)
未找到: 417 (6.0%)
错误: 0 (0.0%)
总体 QPS: 695 req/s
缓存性能:
缓存命中率: 94.01%
数据库查询: 493 (7.1%)
DB QPS: 41.6 req/s
数据库拒绝: 0
DB 利用率: 98.8% (接近满载)
吞吐量放大: 16.7x
延迟:
P50: 1.33µs
P95: 1.12s
P99: 2.04s
延迟分布:
<1ms 93.9% ████████████████████████████████████████████████
<10ms 95.2% █
<100ms 96.4% █
<1s 98.2% █
<10s 100.0% █
💡 关键洞察(冷启动):
- 94.01% 的缓存命中率,即使在 20 秒短刷新策略下
- 98.8% DB 利用率:极小连接池接近满载,充分利用有限资源
- P99 延迟 2.04s,受限于极小连接池的排队压力
- 41.6 DB QPS,吞吐量放大 16.7x
- 零错误冷启动:测试中的连接池排队机制确保无请求被拒绝
- 预热后潜力:命中率可达 99.9%+,DB 利用率将降至 10% 以下,延迟将降至亚秒级
- 展示了缓存在保护极度受限数据库方面的关键作用
| 场景 | P50 | P95 | P99 | 缓存命中率 |
|---|---|---|---|---|
| 高性能 | 791ns | 5.375µs | 5µs | 99.56% |
| 云数据库 | 833ns | 5.25µs | 12µs | 99.62% |
| 共享 | 791ns | 5.833µs | 831ms | 98.57% |
| 受限 | 1.33µs | 1.12s | 2.04s | 94.01% |
📊 观察(冷启动):
- 高性能/云数据库:缓存命中保持在亚微秒到低微秒范围,即使是冷启动
- 共享/受限数据库:P99 延迟较高,主要由连接池排队导致(冷启动压力)
- 预热后改善:缓存预热后,命中率提升至 99.9%+,延迟将显著降低
| 场景 | 并发数 | 应用层 QPS | DB 连接池 | 理论 DB 吞吐 | 吞吐量放大 | DB 利用率 |
|---|---|---|---|---|---|---|
| 高性能 | 600 | 504,989 | 100 | 1,111 QPS | 514.0x | 88.4% |
| 云数据库 | 100 | 55,222 | 20 | 235 QPS | 235.0x | 90.9% |
| 共享 | 100 | 7,306 | 13 | 104 QPS | 70.2x | 99.0% |
| 受限 | 100 | 695 | 8 | 42 QPS | 16.7x | 98.8% |
📊 观察(冷启动):
- 吞吐量放大 = 应用层 QPS / 理论 DB 吞吐量,其中理论 DB 吞吐量 = 连接池大小 / (延迟 / 1000ms)
- 高性能数据库:514.0x 放大,88.4% 利用率,高负载运行同时保留 11.6% 缓冲
- 云数据库:235.0x 放大,90.9% 理想利用率,平衡性能与资源使用
- 共享/受限:70.2x / 16.7x 放大,接近满载(99%+),连接池充分利用
- 关键价值:基于连接池的真实模拟,准确反映数据库在冷启动时的行为
| 场景 | 新鲜 TTL | 使用场景 | DB 连接池 |
|---|---|---|---|
| 高性能 | 3s | 激进刷新,快速响应 | 100 |
| 云数据库 | 5s | 平衡性能与新鲜度 | 20 |
| 共享 | 10s | 保守策略,保护 DB | 13 |
| 受限 | 20s | 非常保守,最大保护 | 8 |
💡 冷启动配置原则:
- TTL 策略根据连接池大小调整,确保冷启动时零错误
- 连接池越小,TTL 越长,以减少冷启动期间的 DB 压力
- 预热后优化:缓存预热后,可以显著缩短 TTL 以提升数据新鲜度
这是最关键的特性! Cachex 通过 Singleflight + DoubleCheck 机制,配合合理的 TTL 配置,即使在冷启动(无预热)场景也能实现优秀的性能表现。在当前测试配置下,所有场景均实现 0% 错误率。
基准测试使用 Semaphore 连接池机制,而非简单的 QPS 计数器。这真实模拟了数据库连接池的排队行为,使结果更接近生产环境。
即使在冷启动场景下,缓存命中率也能达到:
- 高性能/云数据库:99.56%+ 命中率
- 共享/受限数据库:94%+ 命中率(受限于连接池排队)
这些是冷启动结果!缓存预热后:
- 命中率:可提升至 99.9%+
- 吞吐量:将显著提升(DB 负载降至极低水平)
- 延迟:P99 将降至微秒或亚秒级
- DB 利用率:将降至 1-20%
不同场景展示了连接池大小与 TTL 的权衡:
- 大连接池(100):激进 TTL(3s),充足余量
- 中连接池(20):平衡 TTL(5s),90% 利用率
- 小连接池(8-13):保守 TTL(10-20s),接近满载但零错误
从 QPS 限制改为连接池机制的关键价值:
- ✅ 更真实:准确模拟数据库连接池的排队行为
- ✅ 零拒绝:请求排队而非被立即拒绝,
FetchTimeout真正有效 - ✅ 可预测:DB 利用率基于连接容量,易于理解和优化
基准测试使用基于帕累托的流量模式,反映真实电商行为:
// 80% 的流量 → 20 个商品(目录的 0.2%)
// 95% 的流量 → 200 个商品(目录的 2%)
// 99% 的流量 → 1,000 个商品(目录的 10%)这种分布确保:
- 热门商品始终被缓存且新鲜
- 中等商品受益于高缓存命中率
- 冷门商品经过预热以最小化缓存未命中
- 不存在的请求被缓存以防止重复查询
重现这些结果:
go test -bench=BenchmarkProductSearch -benchtime=1xℹ️ 注意: 结果可能因硬件、Go 版本和系统负载而异。基准测试设计为在给定环境中具有确定性和可重现性。