resp-benchmark is a benchmark tool for testing databases that support the RESP protocol, such as Redis, Valkey, and Tair.
Project description
resp-benchmark
English | 中文
一个基于 Rust 构建的 RESP (Redis 序列化协议) 数据库基准测试工具,提供 Python 绑定。用于测试 Redis、Valkey、Tair 等 RESP 兼容数据库的性能。
主要功能
- 支持自定义命令模板和占位符
- 多线程并发测试
- 支持连接池和管道操作
- 支持 Redis 集群模式
- 提供 CLI 工具和 Python 库接口
- 内置 QPS 限流控制
- Lua 脚本支持:使用 Lua 脚本生成复杂的测试命令
安装
需要 Python 3.9 或更高版本。
pip install resp-benchmark
快速开始
命令行使用
# 基础基准测试
resp-benchmark -s 10 "SET {key uniform 100000} {value 64}"
# 加载数据然后测试
resp-benchmark --load -n 1000000 "SET {key sequence 100000} {value 64}"
resp-benchmark -s 10 "GET {key uniform 100000}"
# 自定义连接数和管道
resp-benchmark -c 128 -P 10 -s 30 "SET {key uniform 1000000} {value 128}"
# 使用 Lua 脚本
resp-benchmark --lua -s 10 "local key = bench.key(10000, 'uniform', 'test'); function generate() return {'SET', key(), bench.value(64)()} end"
# 使用 Lua 脚本文件
resp-benchmark --lua-file -s 10 workloads/hello.lua
Python 库使用
from resp_benchmark import Benchmark
# 初始化基准测试
bm = Benchmark(host="127.0.0.1", port=6379)
# 加载测试数据
bm.load_data(
command="SET {key sequence 1000000} {value 64}",
count=1000000,
connections=128
)
# 运行基准测试
result = bm.bench(
command="GET {key uniform 1000000}",
seconds=30,
connections=64
)
print(f"QPS: {result.qps}")
print(f"平均延迟: {result.avg_latency_ms}ms")
print(f"P99 延迟: {result.p99_latency_ms}ms")
# 使用 Lua 脚本
lua_script = """
local user_id = bench.key(10000, "uniform", "user_id")
local data = bench.value(64)
function generate()
key = user_id()
value = data()
return { "SET", key, value }
end
"""
result = bm.bench(command=lua_script, seconds=30, connections=64, use_lua=True)
命令语法
resp-benchmark 使用强大的占位符系统来生成多样化和真实的测试数据:
键占位符
-
{key uniform N}: 从 0 到 N-1 的随机键- 示例:
{key uniform 100000}→key_0000099999
- 示例:
-
{key sequence N}: 从 0 到 N-1 的顺序键(适用于加载数据)- 示例:
{key sequence 100000}→key_0000000000,key_0000000001, ...
- 示例:
-
{key zipfian N}: Zipfian 分布键(模拟真实世界的访问模式)- 示例:
{key zipfian 100000}→ 遵循指数为 1.03 的 Zipfian 分布
- 示例:
值占位符
-
{value N}: N 字节的随机字符串- 示例:
{value 64}→a8x9mK2p...(64 字节)
- 示例:
-
{rand N}: 0 到 N-1 的随机数- 示例:
{rand 1000}→742
- 示例:
-
{range N W}: 范围 N 内相差 W 的两个数字- 示例:
{range 100 10}→45 55
- 示例:
命令示例
# 字符串操作
SET {key uniform 1000000} {value 64}
GET {key uniform 1000000}
INCR {key uniform 100000}
# 列表操作
LPUSH {key uniform 1000} {value 64}
LINDEX {key uniform 1000} {rand 100}
# 集合操作
SADD {key uniform 1000} {value 64}
SISMEMBER {key uniform 1000} {value 64}
# 有序集合操作
ZADD {key uniform 1000} {rand 1000} {value 64}
ZRANGEBYSCORE {key uniform 1000} {range 1000 100}
# 哈希操作
HSET {key uniform 1000} {key uniform 100} {value 64}
HGET {key uniform 1000} {key uniform 100}
Lua 脚本支持
resp-benchmark 现在支持使用 Lua 脚本来生成更复杂的测试命令。
Lua API
在 Lua 脚本中,可以通过全局对象 bench 访问以下函数:
bench.key(range, distribution, name)
创建一个键生成器:
range: 键的范围(0 到 range-1)distribution: 分布类型("uniform"、"sequence"、"zipfian")name: 生成器名称(用于在多个脚本实例间共享状态),同名生成器将共享状态。
返回一个可调用的函数,每次调用生成下一个键。
bench.value(size)
创建一个值生成器:
size: 生成的随机字符串长度(字节数)
返回一个可调用的函数,每次调用生成指定长度的随机字符串。
bench.rand(range)
创建一个随机数生成器:
range: 随机数范围(0 到 range-1)
返回一个可调用的函数,每次调用生成一个随机整数。
json.encode(data)
将 Lua 表转换为 JSON 字符串。
Lua 脚本要求
每个 Lua 脚本必须定义一个名为 generate 的全局函数,该函数不接受参数并返回一个字符串数组,表示 Redis 命令。
function generate()
-- 生成命令逻辑
return { "COMMAND", "arg1", "arg2", ... }
end
Lua 示例
基础示例
local key_gen = bench.key(10000, "uniform", "my_key")
local value_gen = bench.value(64)
function generate()
return { "SET", key_gen(), value_gen() }
end
带条件逻辑的示例
local key_gen = bench.key(10000, "uniform", "cond_key")
local value_gen = bench.value(64)
local rand_gen = bench.rand(100)
function generate()
local key = key_gen()
local value = value_gen()
local num = rand_gen()
if num < 50 then
return { "SET", key, value }
else
return { "GET", key }
end
end
复杂数据结构示例
local key_gen = bench.key(1000, "uniform", "hash_key")
local field_gen = bench.key(100, "zipfian", "hash_field")
local value_gen = bench.value(32)
function generate()
local key = key_gen()
local field = field_gen()
local value = value_gen()
return { "HSET", key, field, value }
end
使用 JSON 编码的示例
local key_gen = bench.key(1000, "uniform", "json_key")
local id_rand = bench.rand(10000)
local name_rand = bench.rand(1000)
local score_rand = bench.rand(100)
function generate()
local data = {
id = id_rand(),
name = "user_" .. name_rand(),
score = score_rand()
}
local json_str = json.encode(data)
local key = key_gen()
return { "SET", key, json_str }
end
命令行选项
| 选项 | 描述 | 默认值 |
|---|---|---|
-h |
服务器主机名 | 127.0.0.1 |
-p |
服务器端口 | 6379 |
-u |
认证用户名 | "" |
-a |
认证密码 | "" |
-c |
连接数(0 为自动) | 0 |
-n |
总请求数(0 为无限) | 0 |
-s |
持续时间(秒)(0 为无限) | 0 |
-t |
目标 QPS(0 为无限) | 0 |
-P |
管道深度 | 1 |
--cores |
使用的 CPU 核心(逗号分隔) | 全部 |
--cluster |
启用集群模式 | false |
--load |
仅加载数据,不进行基准测试 | false |
--short-connection |
短连接模式:每次命令都创建新连接 | false |
--lua |
使用 Lua 脚本生成随机命令 | false |
--lua-file |
使用 Lua 脚本文件生成随机命令 | false |
高级特性
连接自动扩展
当指定 -c 0 时,resp-benchmark 根据系统资源和目标 QPS 自动确定最优连接数。
CPU 核心绑定
将基准测试线程绑定到特定 CPU 核心以获得一致的性能:
# 使用核心 0, 1, 2, 3
resp-benchmark --cores 0,1,2,3 -s 10 "SET {key uniform 100000} {value 64}"
速率限制
控制请求速率进行渐进式负载测试:
# 目标 10,000 QPS
resp-benchmark -t 10000 -s 30 "SET {key uniform 100000} {value 64}"
管道操作
使用管道进行批量操作:
# 每个连接管道 10 个请求
resp-benchmark -P 10 -c 128 -s 30 "SET {key uniform 100000} {value 64}"
集群模式
使用自动槽位分布测试 Redis 集群:
resp-benchmark --cluster -h cluster-endpoint -p 7000 -s 30 "SET {key uniform 100000} {value 64}"
性能优化
最佳实践
- 预加载数据: 使用
--load在基准测试前填充测试数据 - 适当的连接数: 从
-c 128开始,根据结果调整 - 键分布: 读取使用
uniform,写入使用sequence - 明智使用管道: 批量操作使用
-P 10,延迟测试使用-P 1 - 清洁状态: 测试之间清除数据以避免干扰
示例工作流程
# 1. 清除现有数据
redis-cli FLUSHALL
# 2. 加载测试数据
resp-benchmark --load -c 256 -P 10 -n 1000000 "SET {key sequence 100000} {value 64}"
# 3. 使用不同模式进行基准测试
resp-benchmark -c 128 -s 30 "GET {key uniform 100000}" # 随机访问
resp-benchmark -c 128 -s 30 "GET {key zipfian 100000}" # 真实访问模式
完整示例
字符串操作
# 基本 SET/GET
resp-benchmark --load -n 1000000 "SET {key sequence 100000} {value 64}"
resp-benchmark -s 10 "GET {key uniform 100000}"
# 大值
resp-benchmark -s 10 "SET {key uniform 10000} {value 1024}"
# 递增操作
resp-benchmark -s 10 "INCR {key uniform 10000}"
列表操作
# 构建列表
resp-benchmark --load -n 1000000 "LPUSH {key sequence 1000} {value 64}"
# 随机访问
resp-benchmark -s 10 "LINDEX {key uniform 1000} {rand 1000}"
# 范围操作
resp-benchmark -s 10 "LRANGE {key uniform 1000} {range 1000 10}"
集合操作
# 填充集合
resp-benchmark --load -n 1000000 "SADD {key sequence 1000} {key sequence 1000}"
# 测试成员关系
resp-benchmark -s 10 "SISMEMBER {key uniform 1000} {key uniform 1000}"
有序集合操作
# 添加带分数的成员
resp-benchmark --load -n 1000000 "ZADD {key sequence 1000} {rand 10000} {key sequence 1000}"
# 分数查询
resp-benchmark -s 10 "ZSCORE {key uniform 1000} {key uniform 1000}"
# 范围查询
resp-benchmark -s 10 "ZRANGEBYSCORE {key uniform 1000} {range 10000 100}"
哈希操作
# 填充哈希
resp-benchmark --load -n 1000000 "HSET {key sequence 1000} {key sequence 100} {value 64}"
# 字段访问
resp-benchmark -s 10 "HGET {key uniform 1000} {key uniform 100}"
Lua 脚本
# 加载脚本
redis-cli SCRIPT LOAD "return redis.call('SET', KEYS[1], ARGV[1])"
# 基准测试脚本执行
resp-benchmark -s 10 "EVALSHA d8f2fad9f8e86a53d2a6ebd960b33c4972cacc37 1 {key uniform 100000} {value 64}"
短连接性能测试
短连接模式:每次命令都创建新连接,执行完成后立即关闭。
限制:
- 不支持
--load和-P(pipeline 必须为 1)
使用:
resp-benchmark --short-connection "PING" -c 50 -s 10
Python API:
result = bm.bench(command="PING", seconds=30, connections=50, short_connection=True)
Python 库 API
初始化
from resp_benchmark import Benchmark
# 基本连接
bm = Benchmark(host="127.0.0.1", port=6379)
# 带认证
bm = Benchmark(
host="redis.example.com",
port=6379,
username="user",
password="pass"
)
# 集群模式
bm = Benchmark(
host="cluster-endpoint",
port=7000,
cluster=True
)
# 自定义配置
bm = Benchmark(
host="127.0.0.1",
port=6379,
cores="0,1,2,3", # 使用特定核心
timeout=30 # 连接超时
)
加载数据
# 顺序加载(推荐)
bm.load_data(
command="SET {key sequence 1000000} {value 64}",
count=1000000,
connections=128,
pipeline=10
)
# 带速率限制
bm.load_data(
command="SET {key sequence 1000000} {value 64}",
count=1000000,
connections=128,
target=50000 # 50k QPS
)
基准测试
# 基于时间的基准测试
result = bm.bench(
command="GET {key uniform 1000000}",
seconds=30,
connections=64
)
# 基于计数的基准测试
result = bm.bench(
command="GET {key uniform 1000000}",
count=1000000,
connections=64
)
# 带管道
result = bm.bench(
command="SET {key uniform 1000000} {value 64}",
seconds=30,
connections=64,
pipeline=10
)
# 短连接模式
result = bm.bench(
command="PING",
seconds=30,
connections=50,
short_connection=True
)
结果分析
# 访问基准测试结果
print(f"QPS: {result.qps:.2f}")
print(f"平均延迟: {result.avg_latency_ms:.2f}ms")
print(f"P99 延迟: {result.p99_latency_ms:.2f}ms")
print(f"使用的连接数: {result.connections}")
贡献
欢迎贡献!请随时提交拉取请求或开启议题。
许可证
该项目基于 MIT 许可证 - 详见 LICENSE 文件。
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file resp_benchmark-0.2.3.tar.gz.
File metadata
- Download URL: resp_benchmark-0.2.3.tar.gz
- Upload date:
- Size: 42.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
547252482f7aad0e4bb16eef09bf9c389415fe00bc13f54d3607e4c2d2a56c7e
|
|
| MD5 |
3443c6db62c9eb4f56c6744e5470545d
|
|
| BLAKE2b-256 |
49bad2b74ee24a19d39f342d09f21a5c2d232186e03989f07e666c9c5948c277
|
File details
Details for the file resp_benchmark-0.2.3-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: resp_benchmark-0.2.3-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8387256ada61194d192db094f61a7ec8375e05a4313ec4c15559cc364c91de1c
|
|
| MD5 |
7fd732471b987501ff97d5c0b2c91558
|
|
| BLAKE2b-256 |
aeba4d0a0988ac4579b5f32493d368137f29e5b01e11dc1958d69eaad0fc6ab8
|