Siberite性能基准测试实战:复现70K QPS洪峰测试并与Kestrel、Darner内存占用对比
Siberite性能基准测试实战:复现70K QPS洪峰测试并与Kestrel、Darner内存占用对比
【免费下载链接】siberiteSiberite is a simple, lightweight, leveldb backed message queue written in Go.项目地址: https://gitcode.com/gh_mirrors/si/siberite
Siberite 是一个用 Go 编写的轻量级、基于 LevelDB 的持久化消息队列服务器。本文带你实战复现 Siberite 的性能基准测试:从70K QPS 洪峰吞吐量,到与经典队列 Kestrel、Darner 的内存占用对比,用真实数据回答"这个小而美的队列到底能扛多少量"。
🧪 为什么 Siberite 值得做性能基准测试
Siberite 的定位很明确:
- 持久化优先:所有消息都落在 LevelDB 磁盘存储中(存储引擎封装在 queue/queue.go 中),队列可以比内存大得多;
- 内存极省:不管队列里堆了多少消息,常驻内存始终很低;
- 协议兼容:沿用 memcache TCP 文本协议,几乎所有 memcached 客户端都能直接用,官方兼容客户端清单见 docs/clients.md。
对新手来说,这类服务最怕"平时很稳、一上量就崩"。所以官方专门维护了一套完整的基准测试方案,原始数据与图表都集中在 docs/benchmarks.md。
📋 测试环境与三套基准测试方案
测试环境(来自官方基准文档):MacBook Pro(2.2 GHz Intel Core i7 / 16 GB DDR3 / SSD),OS X Yosemite。对比版本为 Kestrel 2.4.8(Java,-Xmx1024m)、Darner 0.2.5(RocksDB)、Siberite 0.5.1。
测试脚本全部位于bench/bench/目录,核心是一个 Go 编写的压测客户端 bench.go,它模拟多并发连接做 set/get 操作:
| 测试 | 脚本 | 测什么 |
|---|---|---|
| 洪峰吞吐 | flood.sh | 10 个队列在高并发下的原始吞吐量(QPS) |
| 积压吞吐 | packing.sh | 队列堆满大消息后,性能会不会崩 |
| 常驻内存 | mem_rss.sh | 队列膨胀再收缩后的实际内存占用 |
🚀 洪峰吞吐量测试:100 并发冲到 7.4 万 QPS
洪峰测试的思路是:预先让队列里始终有消息可取,然后用 1 ~ 8000 不等的并发连接对 10 个队列疯狂 set/get,观察每秒请求数(QPS)如何随并发变化。
结果非常能打:
| 队列服务器 | 峰值吞吐 | 峰值出现时的并发数 |
|---|---|---|
| Siberite | 74,224 QPS | 100 |
| Kestrel | 62,213 QPS | 300 |
| Darner | 56,427 QPS | 50 |
几个值得新手注意的点:
- Siberite 在 100 并发就摸到 7.4 万 QPS 的峰值,比 Kestrel 高约 19%;
- 三者都遵循"并发增加到某个点后吞吐不再涨"的规律——这是压测中判断服务瓶颈位置的经典信号;
- 在 2000 并发以上的高压区,Siberite(49,407 QPS)明显甩开 Kestrel(57,317 → 6000 并发时已跌至 33,423)与 Darner。
📦 大消息积压测试:队列堆 800 万条后依然平稳
第二个测试更贴近生产:消息只有 1KB,但先把队列堆到最多 838 万条(约 8 GB,远超内存容量),再测此时的读写吞吐。这种场景下绝对速度不重要,重要的是"不掉链子"。
| 积压条数 | Kestrel | Darner | Siberite |
|---|---|---|---|
| 0 条(空队列) | 16,278 | 17,388 | 16,084 |
| 65,536 条 | 16,376 | 13,189 | 13,507 |
| 8,388,608 条 | 15,116 | 14,756 | 12,316 |
三条曲线都呈"先小幅下滑、随后走平"的形态,说明当消息溢出内存、必须从磁盘读时,三款服务器都能维持稳定吞吐。Siberite 的曲线在 26 万条后几乎是一条直线,波动最小。
64 字节小消息的积压 + 出队测试(脚本 packing_unpacking.sh)则考验 LevelDB 面对海量删除操作是否会退化——2.65 亿条消息的极限场景下,三者吞吐都稳定在 1.5 万~1.7 万 ops/s 区间,Siberite 全程保持在 1.4 万~1.6 万 ops/s,没有出现性能悬崖。
💾 内存占用对比:Kestrel 的 1/9
这才是 Siberite 的主场。内存测试会不断把 1KB 消息灌入队列(0 → 52 万条)再全部读出,用ps采集服务进程的常驻内存(RSS)。
| 队列规模(1KB 消息) | Kestrel | Darner | Siberite |
|---|---|---|---|
| 0 条 | 182 MB | 2.8 MB | 3.1 MB |
| 65,536 条 | 454 MB | 45 MB | 61 MB |
| 262,024 条 | 746 MB | 50 MB | 86 MB |
| 524,048 条 | 820 MB | 53 MB | 92 MB |
结论一目了然:
- Kestrel 的常驻内存随队列规模线性膨胀,52 万条消息就吃掉约 820 MB(还在逼近 1GB 的 -Xmx 上限);
- Siberite 虽然比 Darner 略高,但内存曲线明显更平缓,且消息全部持久化在磁盘上,队列再大也不会把内存吃爆;
- 对新手来说这意味着:一台 2GB 的小机器跑 Siberite 处理几十 GB 的积压队列,是完全可行的。
🔁 如何快速复现这套 Siberite 基准测试
想亲手验证数据?三步走:
1️⃣ 克隆仓库并编译服务
git clone https://gitcode.com/gh_mirrors/si/siberite cd siberite go build siberite.go mkdir ./data ./siberite -listen localhost:22135 -data ./data2️⃣ 启动压测客户端
压测客户端就是bench/bench/下的 bench.go,常用参数:-port(端口)、-concurrency(并发数)、-sets/-gets(读写次数)、-queues(队列数)、-item_size(消息大小)。
3️⃣ 直接跑压测命令
官方脚本 flood.sh 需要同时部署 Kestrel 和 Darner 才能出完整对比图;只测 Siberite 的话,直接模拟脚本中的洪峰场景即可:
cd bench/bench ./bench -port 22135 -sets 10000 -gets 10000 -queues 10 -concurrency 100把-concurrency换成 1、10、100、1000 等值,你会亲眼看到吞吐随并发爬升、在 100 并发附近到达峰值的完整曲线。
✅ 新手选型速查:Siberite 适合谁
- ✅ 队列规模可能远超内存、需要磁盘级持久化 → Siberite 是省心之选
- ✅ 追求低常驻内存,想在低配机器上跑队列 → 92 MB 搞定 52 万条消息
- ✅ 已有 memcached 生态客户端,不想改协议 → 直接连
- ⚠️ 需要毫秒级超低延迟的纯内存缓存 → 优先考虑 Redis 这类内存型方案
- ⚠️ 需要复杂路由、事务等企业特性 → 考虑 RabbitMQ 这类重量级方案
一句话总结:在 100 并发下 7.4 万 QPS 的洪峰吞吐、积压 800 万条消息后吞吐平稳、52 万条消息仅占 92 MB 常驻内存——Siberite 用一份完整可复现的基准测试(docs/benchmarks.md)证明了:轻量级持久化消息队列,也能打出硬实力。
【免费下载链接】siberiteSiberite is a simple, lightweight, leveldb backed message queue written in Go.项目地址: https://gitcode.com/gh_mirrors/si/siberite
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
