我正在尝试在NodeJS应用程序中将所有Redis密钥与MongoDB同步。
我将ioredis用作NodeJS Redis客户端,并尝试通过使用scanStream() function来实现上述目的。据说,此功能是使用流通过游标浏览光标中所有键的简便方法。
这是我用来尝试浏览所有键的代码:
const stream = await redis.scanStream();
stream.on("data", async (resultKeys) => {
await stream.pause();
for (let i = 0; i < resultKeys.length; i++) {
try {
let KEY = resultKeys[i];
let redisObjectStr = await redis.get(KEY);
let redisObject = JSON.parse(redisObjectStr);
// Sync Redis key with MongoDB
const user = await User.findOne({
apiKey: KEY
}).exec();
if (user) {
user.color = redisObject.color;
user.size = redisObject.size;
await user.save();
await stream.resume();
}
} catch (err) {
next(err)
}
}
});
stream.on("end", () => {
console.log("all keys have been visited")
res.send("done")
})
但是我遇到以下错误:
api_1 |已访问所有密钥proxy_1 | 172.18.0.1-- [22 / Jan / 2019:12:52:06 +0000]“ GET / api / syncredis HTTP / 1.1” 200 4“-” “ PostmanRuntime / 7.6.0”“-” api_1 | :: ffff:172.18.0.6-- [22 / Jan / 2019:12:52:06 +0000]“ GET / api / syncredis HTTP / 1.1” 200 4“-” “ PostmanRuntime / 7.6.0” api_1 |语法错误:意外的令牌l in 位置0 api_1处的JSON |在JSON.parse()api_1处 |在ScanStream.stream.on (/usr/src/app/routes/testRoute.js:428:32)api_1 |在 process.internalTickCallback(内部/进程/next_tick.js:77:7) api_1 |错误[ERR_HTTP_HEADERS_SENT]:之后无法设置标题 它们被发送给客户
答案 0 :(得分:0)
我假设您使用的是简单的Redis,而不是群集的Redis。您应该尝试将其包装在Promise中,以便它直接跳转到stream.end,并检查从redis.get获得的结果,检查是否为正确的可解析json字符串。
我建议从不同的函数中获取所有键,然后迭代与mongo同步的所有键。
代码:-
let arrOfKeys = await getKeys(prefix);
//loop through all the keys and sync with mongo
const getKeys = async (prefix = "") => {
let finalKeyArray = [], keysArray = [];
let stream = redis.scanStream({
match: prefix
});
return new Promise((res, rej) => {
stream.on("data", async (keys = []) => {
let key;
for (key of keys) {
if (!keysArray.includes(key)) {
await keysArray.push(key);
}
}
});
stream.on("end", () => {
res(keysArray);
});
}).then((keysets) => {
keysets.forEach((keySet) => {
keySet.forEach((key) => {
if (!finalKeyArray.includes(key)) {
finalKeyArray.push(key);
}
})
})
return finalKeyArray;
}).catch((err) => {
console.error("Error while getting redis keys:", err);
return [];
});
}