[英]Using Node.js redis scanIterator correctly
我试图一次从我的 redis 实例中检索 N 个密钥。 在这种情况下,我将 N 个键指定为batchSize = 100
。 此代码似乎无限循环,这表明我没有正确返回 cursor。 output无限循环: got a batch of 719 logs
。 我的测试数据库中共有 719 个键。 所以这在理论上应该循环retrieveLogs
总共 8 次,有 7 批 100,还有一批 19。
我找不到很多关于如何正确使用它的文档,但这是我的整个程序。 我做错了什么吗?
/* eslint-disable no-await-in-loop */
/* eslint-disable no-restricted-syntax */
import { createClient } from 'redis';
const redisClient = createClient({ url: process.env.REDIS_URL });
redisClient.on('error', (err) => {
console.log('Redis Client Error', err);
throw new Error('Redis Client Error');
});
async function retrieveLogs(batchSize) {
const logs = [];
for await (const cursor of redisClient.scanIterator({
MATCH: 'log:*',
COUNT: batchSize,
})) {
const log = await redisClient.get(cursor);
if (log) {
logs.push(JSON.parse(log));
}
if (cursor === '0') {
console.log('breaking');
break;
}
}
return logs;
}
async function main() {
redisClient.on('error', (err) => {
console.log('Redis Client Error', err);
throw new Error('Redis Client Error');
});
await redisClient.connect();
// Set the number of logs to retrieve and delete at a time
const batchSize = 100;
// Set a flag to indicate whether there are more logs to process
let moreLogs = true;
while (moreLogs) {
// Retrieve a batch of logs from Redis
// eslint-disable-next-line no-await-in-loop
const batch = await retrieveLogs(batchSize);
if (batch.length === 0) {
// If there are no logs, set the flag to false to exit the loop
moreLogs = false;
break;
}
console.log(`got a batch of ${batch.length} logs`);
}
await redisClient.disconnect();
}
main();
主要问题是您在每次调用retrieveLogs()
时收集所有结果,而main()
中的while
循环似乎准备好在每次调用时接受一大块项目。 事实并非如此,因为异步迭代器scanIterator()
返回已经允许使用所有SCAN
结果——隐藏了异步迭代器本身的复杂性。
因此,要解决此问题,您可以将while
循环放在main()
中,或者查看逻辑,以便调用scanIterator()
main()
迭代。
// ...
await redisClient.connect();
// Retrieve a batch of logs from Redis
const batch = await retrieveLogs(batchSize);
console.log(`got a batch of ${batch.length} logs`);
// TODO: Use the batch
await redisClient.disconnect();
// ...
此外, scanIterator()
返回键而不是 cursor,因为实际的 cursor 隐藏在异步迭代器实现中。 因此,应该删除异步迭代中的短路逻辑,您可能还想相应地重命名该变量:
for await (const key of redisClient.scanIterator({
MATCH: 'log:*',
COUNT: batchSize,
})) {
const log = await redisClient.get(key);
if (log) {
logs.push(JSON.parse(log));
}
}
并且...保证scanIterator()
返回的键存在,因此您可以(取决于您的解析逻辑)甚至删除对log
的额外真实检查。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.