KEYS 命令返回一些结果:
> keys Types/*/*BackgroundJob.json
1) "Types/Xyz.Data/Xyz.Data.BackgroundJobEngine.BackgroundJob.json"
2) "Types/Xyz.Web.SystemAdmin/Xyz.Web.SystemAdmin.Models.Encryption.EncryptionMethodByBackgroundJob.json"
3) "Types/BackgroundJobs/SharpTop.Engine.BackgroundJobs.AutofillBackgroundJob.json"
4) "Types/Quartz.Server/BJE.UDT.BackgroundJob.json"
5) "Types/DFControllersTest.Compensation/DFControllersTest.Compensation.SubmitCompensationPublishBackgroundJob.json"
6) "Types/SpecFlowTest.Architecture.Base/SpecFlowTest.Architecture.Base.Model.IntStudioConfigBackgroundJob.json"
7) "Types/SpecFlowTest.Benefits.UI/SpecFlowTest.Benefits.UI.Base.Services.BackgroundJobsService+BackgroundJob.json"
8) "Types/Xyz.WFM.ExpressionService.Client/Xyz.WFM.ExpressionService.Client.BackgroundJob.ExpressionManagerBackgroundJob.json"
9) "Types/DFControllersTest.Compensation/DFControllersTest.Compensation.SubmitGenerateBudgetWorksheetBackgroundJob.json"
10) "Types/DFControllersTest.Compensation/DFControllersTest.Compensation.SubmitCompensationUnPublishBackgroundJob.json"
11) "Types/IntegrationStudio/IntegrationStudio.DAL.Entities.IntStudioConfigBackgroundJob.json"
12) "Types/IntegrationStudio/IntegrationStudio.DAL.Entities.BackgroundJob.json"
但使用相同模式的 SCAN 没有返回任何内容:
> scan 0 match Types/*/*BackgroundJob.json
1) "1966080"
2) (empty list or set)
我尝试跟踪返回的游标值几次迭代,但如果不编写脚本来检查它,它似乎只会得到无休止的一系列空结果。
到底是怎么回事?
编辑1
我最终决定对其进行编码:
private async IAsyncEnumerable<string> QueryRedisAsync(string pattern, [EnumeratorCancellation] CancellationToken ct = default)
{
var db = connection.GetDatabase();
var cursor = "0";
int count = 0;
do
{
++count;
ct.ThrowIfCancellationRequested();
var tmp = await db.ExecuteAsync("SCAN", cursor, "MATCH", pattern, "COUNT", "1000");
var scanResult = (RedisResult[])tmp;
cursor = scanResult[0].ToString();
var keys = (RedisKey[])scanResult[1];
foreach (var key in keys)
{
yield return key.ToString();
}
}
while (cursor != "0");
Console.WriteLine(count);
}
代码执行了 1058 (!) 次迭代,其中在某次迭代中恰好发现了一个匹配项,即:
- 173
- 189
- 242
- 351
- 416
- 473
- 590
- 912
- 975
- 983
- 998
- 1027
因此,我SCAN
为了“友好”起见,就这么做,但这导致了 1058 次服务器往返。
我做错什么了吗?
可能重复
我不认为这是redis scan returns empty results but nonzero cursor的重复。为了获得少量结果而对服务器进行 1K+ 次往返似乎不合理。
命令
KEYS
的行为与命令完全不同SCAN
。KEYS
命令会迭代 Redis 中的所有键,并过滤与给定模式匹配的键。这就是为什么一次往返就能给出答案。但是,运行KEYS
命令时,Redis 会阻塞,无法处理其他命令。因此,在生产环境中使用命令是个坏主意KEYS
,尤其是当您拥有大量数据集时。SCAN
命令也会迭代 Redis 中的键。但是,对于每次扫描,它仅检查几个键(您可以使用count
参数来控制键的数量),过滤符合您模式的键并返回。因此,您需要进行多次往返才能迭代 Redis 中的所有键。由于每次扫描操作仅检查几个键,因此它不会长时间阻塞 Redis。这是扫描键空间的推荐方法。因为您的数据集很大,但只有少数几个密钥与您的模式匹配(比例很小)。前 1057 次扫描没有得到与模式匹配的密钥。
是的,
SCAN
比更好KEYS
,特别是当你需要扫描 Redis 中的所有键时(没有指定模式,或者大部分键与模式匹配)。但是,对于你的情况,更好的解决方案是为符合模式的键创建二级索引。比如,你可以将这些键保存在 Redis SET 中,然后扫描该 SET 以获取键。