## 测试口径 - 时间:2026-03-04 - 工具:`./test-redis/bench` - kvstore 测试命令:`RSET/RGET` - Redis 测试命令:`SET/GET` - 通用参数: - 写:`requests=10000 pipeline=128 keyspace=1000000000 value-size=32` - 读:`requests=300000 pipeline=128 keyspace=100000 value-size=32` - kvstore 复测时临时使用 `persistence=none`(避免历史 oplog 回放影响)。 --- ## 优化项 #1:ChainBuffer 接收链路改造 改造点:`readv` 直写 + 回环 chunk + 节点池(减少接收路径中转拷贝)。 ### A. 改造前后(kvstore) | 指标 | 改造前(旧记录,单次) | 改造后(本次,3轮均值) | 变化 | |---|---:|---:|---:| | RSET QPS | 260604 | 331063 | **+27.04%** | | RGET QPS | 288107 | 360581 | **+25.15%** | > 说明:旧值来自此前同文档记录;新值是本次重跑 3 轮的均值,可信度更高。 ### B. 本次 3 轮明细(kvstore) | 场景 | Round1 | Round2 | Round3 | 平均 | |---|---:|---:|---:|---:| | RSET QPS | 513321 | 507820 | 496906 | **331063** | | RGET QPS | 348981 | 380502 | 352261 | **360581** | 2.87 --- ## Redis 对照(同口径复测) ### A. 默认 Redis 实例(127.0.0.1:6379,3轮均值) | 场景 | Round1 | Round2 | Round3 | 平均 | |---|---:|---:|---:|---:| | SET QPS | 299221 | 130792 | 312117 | **247377** | | GET QPS | 349242 | 343573 | 353091 | **348635** | ### B. 与 kvstore 对比(本次均值) | 指标 | kvstore | redis:6379 | 相对变化(kvstore 对 redis) | |---|---:|---:|---:| | 写 QPS | 331063 | 247377 | **+33.83%** | | 读 QPS | 360581 | 348635 | **+3.36%** | > 解释:这说明“kvstore 在当前写路径上有优势,但读路径仍落后 Redis”。 --- ## Redis 持久化策略对比(写压测,SET) | 策略 | QPS | avg(us/op) | 备注 | |---|---:|---:|---| | `none`(无持久化) | **492561** | 2.03 | 最高吞吐(但不持久) | | `rdb_default` | **285885** | 3.50 | 本次“持久化策略中最快” | | `aof_no` | 281870 | 3.55 | AOF,`appendfsync no` | | `aof_everysec` | 266878 | 3.75 | AOF,`appendfsync everysec` | | `aof_always` | 110793 | 9.03 | 最慢,但最强一致性 | 结论: - 如果包含“无持久化”,最快是 `none`。 - 如果限定“必须持久化”,本次最快是 `rdb_default`(略快于 `aof_no`)。 --- ## 历史复现命令(关键) ```bash # kvstore 写(RSET) ./test-redis/bench --host 127.0.0.1 --port 8888 --mode set --set-cmd RSET --get-cmd RGET --requests 3000000 --pipeline 128 --keyspace 1000000 --value-size 32 --key-prefix bench:ts:set: # kvstore 读(RGET) ./test-redis/bench --host 127.0.0.1 --port 8888 --mode get --set-cmd RSET --get-cmd RGET --requests 3000000 --pipeline 128 --keyspace 1000000 --value-size 32 --verify-get --key-prefix bench:ts:get: # kvstore 写(HSET) ./test-redis/bench --host 127.0.0.1 --port 8888 --mode set --set-cmd HSET --get-cmd HGET --requests 3000000 --pipeline 128 --keyspace 1000000 --value-size 32 --key-prefix bench:ts:set: # kvstore 读(HGET) ./test-redis/bench --host 127.0.0.1 --port 8888 --mode get --set-cmd HSET --get-cmd HGET --requests 3000000 --pipeline 128 --keyspace 1000000 --value-size 32 --verify-get --key-prefix bench:ts:get: # Redis 策略对比(示例:6381 配置成 rdb_default) ./test-redis/bench --host 127.0.0.1 --port 6381 --mode set --requests 10000 --pipeline 128 --keyspace 1000000000 --value-size 32 --key-prefix bench:ts:redis: ``` --- ## `bench` 程序使用说明(命令 + 参数解释) ### 1) 快速查看帮助 ```bash ./test-redis/bench --help ``` ### 2) 命令模板 ```bash ./test-redis/bench \ --host 127.0.0.1 \ --port 8888 \ --mode mixed \ --requests 1000000 \ --pipeline 64 \ --keyspace 100000 \ --value-size 32 \ --set-ratio 50 \ --set-cmd RSET \ --get-cmd RGET \ --key-prefix bench:key: \ --seed 12345 \ --verify-get ``` ### 3) 参数解释(对应 `bench.c`) | 参数 | 默认值 | 说明 | |---|---|---| | `--host ` | `127.0.0.1` | 目标服务 IP | | `--port ` | `6379` | 目标服务端口 | | `--mode ` | `mixed` | 压测模式:纯写/纯读/读写混合 | | `--requests ` | `1000000` | 总请求数(不是每秒) | | `--pipeline ` | `64` | pipeline 批量深度 | | `--keyspace ` | `100000` | key 空间大小,key 随机落在 `[0, keyspace)` | | `--value-size ` | `32` | value 字节长度 | | `--set-ratio <0..100>` | `50` | `mixed` 下 SET 比例,GET 比例是 `100-set-ratio` | | `--set-cmd ` | `SET` | 写命令名(如 `SET`/`RSET`) | | `--get-cmd ` | `GET` | 读命令名(如 `GET`/`RGET`) | | `--key-prefix ` | `bench:key:` | key 前缀 | | `--seed ` | 当前时间 | 随机种子;固定后可复现实验 | | `--verify-get` | 关闭 | 开启后校验 GET 返回内容是否与写入值一致 | | `--help` / `-h` | - | 打印帮助 | ## run_hash_bench.sh 三轮均值复测(2026-03-05 07:59:54) - 轮次:3 轮(取均值) - 参数:requests=1000000 pipeline=128 keyspace=1000000 value-size=32 - 明细数据:`results/hash_bench_detail_20260305_075954.csv` - 汇总数据:`results/hash_bench_summary_20260305_075954.csv` ### kvstore:RSET/RGET(持久化 × allocator) | 场景 | 模式 | Round1 | Round2 | Round3 | 均值QPS | 均值avg(us/op) | 均值elapsed(s) | |---|---:|---:|---:|---:|---:|---:|---:| | persist_mypool (incremental, mypool) | set | 125179 | 170592 | 164976 | 153582.33 | 6.64 | 6.64 | | persist_mypool (incremental, mypool) | get | 186087 | 195807 | 193450 | 191781.33 | 5.22 | 5.22 | | nopersist_mypool (none, mypool) | set | 185397 | 189265 | 187515 | 187392.33 | 5.33 | 5.34 | | nopersist_mypool (none, mypool) | get | 195032 | 203252 | 196291 | 198191.67 | 5.05 | 5.05 | | persist_malloc (incremental, malloc) | set | 175529 | 172307 | 181948 | 176594.67 | 5.67 | 5.67 | | persist_malloc (incremental, malloc) | get | 202299 | 207732 | 181749 | 197260.00 | 5.08 | 5.09 | | nopersist_malloc (none, malloc) | set | 162956 | 192052 | 191846 | 182284.67 | 5.52 | 5.52 | | nopersist_malloc (none, malloc) | get | 200417 | 211609 | 196936 | 202987.33 | 4.93 | 4.93 | ### Redis:SET/GET(各持久化模式) | 场景 | 模式 | Round1 | Round2 | Round3 | 均值QPS | 均值avg(us/op) | 均值elapsed(s) | |---|---:|---:|---:|---:|---:|---:|---:| | none (none) | set | 234761 | 247981 | 243948 | 242230.00 | 4.13 | 4.13 | | none (none) | get | 247753 | 284771 | 275492 | 269338.67 | 3.73 | 3.73 | | rdb_default (rdb_default) | set | 245989 | 238020 | 241112 | 241707.00 | 4.14 | 4.14 | | rdb_default (rdb_default) | get | 278725 | 274510 | 276342 | 276525.67 | 3.62 | 3.62 | | aof_no (aof_no) | set | 196100 | 209723 | 201687 | 202503.33 | 4.94 | 4.94 | | aof_no (aof_no) | get | 269520 | 277701 | 270562 | 272594.33 | 3.67 | 3.67 | | aof_everysec (aof_everysec) | set | 201758 | 201078 | 180037 | 194291.00 | 5.16 | 5.16 | | aof_everysec (aof_everysec) | get | 259585 | 269224 | 279181 | 269330.00 | 3.71 | 3.72 | | aof_always (aof_always) | set | 75968 | 78265 | 76608 | 76947.00 | 13.00 | 13.00 | | aof_always (aof_always) | get | 276839 | 271247 | 275017 | 274367.67 | 3.65 | 3.65 |