Skip to content

Latest commit

 

History

History
366 lines (281 loc) · 13.1 KB

File metadata and controls

366 lines (281 loc) · 13.1 KB

Cachex 性能基准测试报告

本文档展示了 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% - 不存在的商品请求

💡 这种分布反映了真实电商模式:少数商品获得大部分流量。

基准测试场景

场景 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% 以下

场景 2:云数据库

模拟云数据库,中等连接池(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% 以下

场景 3:共享数据库

模拟共享数据库环境,小型连接池(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% 以下,延迟显著降低

场景 4:受限数据库

模拟极度受限的数据库,极小连接池(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%+,延迟将显著降低

吞吐量 vs 数据库利用率(冷启动)

场景 并发数 应用层 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 策略(冷启动优化)

场景 新鲜 TTL 使用场景 DB 连接池
高性能 3s 激进刷新,快速响应 100
云数据库 5s 平衡性能与新鲜度 20
共享 10s 保守策略,保护 DB 13
受限 20s 非常保守,最大保护 8

💡 冷启动配置原则

  • TTL 策略根据连接池大小调整,确保冷启动时零错误
  • 连接池越小,TTL 越长,以减少冷启动期间的 DB 压力
  • 预热后优化:缓存预热后,可以显著缩短 TTL 以提升数据新鲜度

关键要点

1. 冷启动性能优化 🔥

这是最关键的特性! Cachex 通过 Singleflight + DoubleCheck 机制,配合合理的 TTL 配置,即使在冷启动(无预热)场景也能实现优秀的性能表现。在当前测试配置下,所有场景均实现 0% 错误率

2. 真实的数据库模拟

基准测试使用 Semaphore 连接池机制,而非简单的 QPS 计数器。这真实模拟了数据库连接池的排队行为,使结果更接近生产环境。

3. 冷启动高缓存效率

即使在冷启动场景下,缓存命中率也能达到:

  • 高性能/云数据库:99.56%+ 命中率
  • 共享/受限数据库:94%+ 命中率(受限于连接池排队)

4. 预热后的巨大潜力 🚀

这些是冷启动结果!缓存预热后:

  • 命中率:可提升至 99.9%+
  • 吞吐量:将显著提升(DB 负载降至极低水平)
  • 延迟:P99 将降至微秒或亚秒级
  • DB 利用率:将降至 1-20%

5. 自适应连接池策略

不同场景展示了连接池大小与 TTL 的权衡:

  • 大连接池(100):激进 TTL(3s),充足余量
  • 中连接池(20):平衡 TTL(5s),90% 利用率
  • 小连接池(8-13):保守 TTL(10-20s),接近满载但零错误

6. 连接池 vs QPS 限制

从 QPS 限制改为连接池机制的关键价值:

  • 更真实:准确模拟数据库连接池的排队行为
  • 零拒绝:请求排队而非被立即拒绝,FetchTimeout 真正有效
  • 可预测:DB 利用率基于连接容量,易于理解和优化

流量分布详情

基准测试使用基于帕累托的流量模式,反映真实电商行为:

// 80% 的流量 → 20 个商品(目录的 0.2%)
// 95% 的流量 → 200 个商品(目录的 2%)
// 99% 的流量 → 1,000 个商品(目录的 10%)

这种分布确保:

  • 热门商品始终被缓存且新鲜
  • 中等商品受益于高缓存命中率
  • 冷门商品经过预热以最小化缓存未命中
  • 不存在的请求被缓存以防止重复查询

运行基准测试

重现这些结果:

go test -bench=BenchmarkProductSearch -benchtime=1x

ℹ️ 注意: 结果可能因硬件、Go 版本和系统负载而异。基准测试设计为在给定环境中具有确定性和可重现性。