我正在尝试使用 KeyDB 来查看是否可以获得以及可以获得多少性能改进,因为 Redis 单线程查询模型肯定存在瓶颈。所以我找到了 KeyDB,他们说他们使用“真正的”多线程对数据库进行并行查询,这与 Redis 不同,它只有 IO 多线程而不是实际查询。
从上面的文档链接:
与 Redis6 和 Elasticache 不同,KeyDB 多线程有几个方面,包括将事件循环放置在多个线程上,使用网络 IO,以及同时完成查询解析。
我的简单测试设置:
- 首先,我在 Ubuntu (WSL2) 上安装 KeyDB 并让它运行
- 我注意到启动 KeyDb 时,有 2 个线程处于活动状态:
Thread 0 alive.
Thread 1 alive.
- 我注意到启动 KeyDb 时,有 2 个线程处于活动状态:
- 我修改了 keydb.conf 以禁用一些保存/持久化,但最重要的是,我将
server-threads
选项更改为 2:server-threads 2
。注意:我也尝试过不使用配置文件,只添加 cmd 标志--server-threads 2
并将线程设置为 4,没有区别。 - 然后我运行一个简单的脚本:
- 使用一些简单的 JSON 对象在散列中创建 1M 条目
- 创建一个使用两个线程的简单控制台应用程序;一个线程开始在循环中执行非常简单的 SET (
SET key1 1
) 或 GET ( ),而另一个线程从哈希 ( )GET key1 1
中“获取所有” 。HGETALL testhash
第二个线程在开始其“长查询”之前等待 1 秒。
可以在此处找到 GitHub 存储库(使用 StackExchange.Redis 库)。
我的期望:
我希望简单的快速 SET/GET 每次都花费大约相同的时间,而不会因为长查询运行时 KeyDB 中的阻塞而导致任何延迟或节流。
怎么了:
在长查询运行时,简单的快速 SET/GET 会被阻塞/延迟大约 500-700 毫秒,这表明只有一个线程正在使用,因此会阻塞其他操作。这符合 Redis 的工作方式,以及我希望使用 KeyDB 避免的情况。
日志:
“开始长查询”是当我们执行时HGETALL
,几乎立即执行,简单的 SET 被限制并占用超过 500 毫秒,而它应该占用 0-1 毫秒,如之前和之后所见。
使用 ServiceStack Redis 客户端:
10:50:55.336 GetValueFromHashAsync took 1
10:50:55.367 GetValueFromHashAsync took 1
10:50:55.397 GetValueFromHashAsync took 0
10:50:55.416 Starting long query
10:50:56.191 GetValueFromHashAsync took 766 <-- THROTTLED! Delayed with what I think is the actual query time, not the IO part, so at this point, the line fetching data has not completed yet
10:50:56.228 GetValueFromHashAsync took 0
10:50:56.261 GetValueFromHashAsync took 1
....
....
10:51:00.592 GetValueFromHashAsync took 1
10:51:00.620 GetValueFromHashAsync took 1
10:51:00.651 GetValueFromHashAsync took 1
10:51:00.663 Long query done in 5244 <-- The long query returns here, line is completed, total time was about 5 seconds, while the block was about 0.7 seconds
我也测试过从哈希而不是 SET 中获取,同样的事情。
使用 StackExchange.Redis:在 GitHub reproducable 项目中,在这里找到,我使用的是 StackExchange.Redis 而不是 ServiceStack,我得到了不同的(更糟糕的!)行为:
11:27:12.084 HashGetAsync took 0
11:27:12.115 HashGetAsync took 0
11:27:12.146 HashGetAsync took 0
11:27:12.177 HashGetAsync took 1
11:27:12.183 Starting long query
11:27:14.877 Long query done in 2692
11:27:14.893 HashGetAsync took 2686 <-- THROTTLED! This time the other thread is delayed the entire time, query + IO.
11:27:14.929 HashGetAsync took 0
11:27:14.960 HashGetAsync took 0
11:27:14.992 HashGetAsync took 0
11:27:15.023 HashGetAsync took 0
11:27:15.053 HashGetAsync took 0
结论
无论我使用什么客户端库,KeyDB 都会在运行“长查询”时限制请求/查询,即使我有 2 个线程。如果我用 4 个线程启动 KeyDB 并没有关系,同样的行为。
我不知道为什么 StackExchange 的行为与 ServiceStack 不同,但这不是现在的主要问题。