为什么不应该在生产环境的Redis中使用KEYS进行验证的原因
我认为在Redis中经常使用的命令之一是KEYS。在官方文档中,它被写成以下这样,但我想具体了解为什么它不可取。
警告:请谨慎使用命令KEYS,仅在生产环境中使用。当对大型数据库执行此命令时,可能会影响性能。该命令旨在用于调试和特殊操作,例如更改键空间布局。
进行实验
-
- CentOS Linux release 7.4.1708 (Core)
-
- Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
-
- DDR4 16GB RAM
- redis-server 5.0.7
在该环境下,同时执行对于KEY和SCAN的操作,然后测量redis-benchmark的每秒请求数(RPS)。
准备好
运行redis-server
docker run --rm -it --name redis -p6379:6379 redis:5.0.7
redis-benchmark的启动方式
redis-benchmark -t get -c 1
以Rust编写的程序
使用futures库中的future和prelude模块以及redis库中的Client和Commands模块;
使用structopt库的StructOpt模块;
使用tokio库的Builder模块。
#[derive(StructOpt)]宏定义一个Opt枚举,其中包含Setup、Keys、Scan、BenchKeys和BenchScan几个选项。
#[derive(StructOpt)]宏定义一个BenchOpt结构体,其中包含count和pipeline字段。
fn main()函数开始执行,获取命令行参数opt(Opt枚举类型);
创建redis客户端实例redis,并连接到本地Redis服务;
创建一个tokio运行时实例rt,并指定使用一个核心线程;
获取程序开始执行的时间start。
根据opt的取值,执行相应的逻辑:
– 如果是Setup选项,则根据count值设置一定数量的键值对;
– 如果是Keys选项,则循环执行”KEYS”命令,并输出获取到的结果;
– 如果是Scan选项,则循环执行”SCAN”命令,在匹配到指定的键时输出结果;
– 如果是BenchKeys选项,则以并行连接的方式执行一定数量的”KEYS”命令,并计算请求频率;
– 如果是BenchScan选项,则以并行连接的方式执行一定数量的”SCAN”命令,并计算请求频率。
在执行对应逻辑的过程中,根据需要进行错误处理和打印。最后输出程序的执行时间。
- テストデータ作成
cargo run -- setup -c <NUM_KEYS>
- KEYSを続けて実行し続ける
cargo run -- keys
- SCANを続けて実行し続ける
cargo run -- scan
结果 (jié guǒ)
当使用KEYS命令时,随着Redis的键数量增加,redis-benchmark的RPS会显著变慢。与未执行任何操作相比,SCAN命令稍微变慢,但无论键的数量增加多少,RPS都保持稳定。
以下是测量结果的原始数据。
redis-benchmark每秒请求数(RPS)
1,000
29,638.41
10,000
29,994.00
100,000
30,165.91
500,000
29,761.91
1,000,000
29,931.16
5,000,000
29,205.61
10,000,000
28,719.13
redis-benchmark的RPS
1,000
16353.23
10,000
3630.82
100,000
373.79
500,000
31.03
1,000,000
14.02
5,000,000
2.52
10,000,000
1.08
redis-benchmark的RPS
1,000
26,413.10
10,000
25,940.34
100,000
25,974.03
500,000
25,806.45
1,000,000
25,680.53
5,000,000
23,900.57
10,000,000
24,473.81
总结
KEYSはRedis全体のKeyの数に対してO(N)
Redisのメインの処理はシングスレッドで行われる
本番環境ではKEYSではなくSCANを使うこと
Redisのスレッドを完全にblockしてもいい場合のみだけKEYSを使おう
これらのことは全てドキュメントに書いてある