使用ioredis scanStream()扫描所有Redis密钥时出现问题

时间:2019-01-22 13:01:38

标签: node.js redis ioredis

我正在尝试在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]:之后无法设置标题   它们被发送给客户

1 个答案:

答案 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 [];
    });
}