Redis服务器可以设置数据但是获取不到

Can set data in Redis server but can't get it

我可以在我的 Redis 服务器中设置一个键的值(当我 flushall、运行 这段代码,然后在 redis-cli 中获取键时,我得到正确的值),但是当我尝试通过我的 NodeJs 服务器获取键值时,它甚至从未注销 'got data'.

我想这可能是因为这些函数 运行 是异步的,我要求获取尚未存储在缓存中的值,但这并不能解释为什么它不会打印'got data' 曾经。

我的控制台日志-> 'start'->'data saved'->'end'(没有 'got data',永远)

redis-cli->flushall->get test->(nil)->run app.js(在另一个终端)->get test->" 1、2、3、4、5" 我完全没有错误,代码 运行s,但没有按照我的意愿去做。

另外,不知道这是否相关,但是当连接到Redis服务器时,只是Redis.createClient()只创建了一个客户端但没有连接,当我查找时,我得到了一般的想法是较新的版本没有自动连接,您必须手动 redisClient.connect().

一开始我遇到了一些问题,但似乎已经解决了这个问题,但只是想我会提到它,如果我以某种方式搞砸了,请纠正我,因为我对 NodeJs 很陌生并且一般编码。

我的代码:

const redisClient = Redis.createClient();
redisClient.connect();
const data = [1, 2, 3, 4, 5];
app.get('/', async(req, res, next) => {
    console.log('start')
    await redisClient.set('test', data);
    console.log('data saved');
    await redisClient.get('test', (error, test)=>{ 
        console.log('got data');
        console.log(test);
    });
    console.log('end');
});

谢谢!

我看过你的代码。根据我的调查,您应该删除回调并仅在从 Redis 获取数据时保持等待。

我对这个问题进行了更多调查,发现 client.get()client.set() 函数异步运行。所以才会这样实现。

client.set('foo', 'bar', (err, reply) => {
    if (err) throw err;
    console.log(reply);

    client.get('foo', (err, reply) => {
        if (err) throw err;
        console.log(reply);
    });
});

但每次都不一样use-case 我们应该立即设置并获取值。

要摆脱这个,以下是选项。

  • Promisesasync/await

  • 您可以使用本机 Node.js promisesutil.promisify:

    一次承诺一个 node_redis 函数的子集

    示例:

     const redis = require('redis');
     const { promisify } = require('util');
    
     const runApplication = async () => {
         const client = redis.createClient();
    
         const setAsync = promisify(client.set).bind(client);
         const getAsync = promisify(client.get).bind(client);
    
         await setAsync('foo', 'bar');
         const fooValue = await getAsync('foo');
         console.log(fooValue);
     };
    

我在这里使用了await,解决了一个问题。除此之外,您还可以使用 redis.get().then() 来获取数据而不是回调。

我还附加了 link 和 redis repo 提供的示例 https://github.com/redis/node-redis/blob/master/examples/connect-as-acl-user.js

下面是代码,我已经测试过了,现在可以正常工作了。

redis.js

const redis = require("redis");
const redisClient = redis.createClient({
  url: "redis://host:6379",
  password: "password",
});
redisClient.connect();

// const { promisify } = require("util");
// promisify(redisClient.get).bind(redisClient);
// promisify(redisClient.set).bind(redisClient);

module.exports = redisClient;

index.js

const express = require("express");
const app = express();
const redisClient = require("./redis");

app.get("/set", async (req, res, next) => {
  try {
    const data = req.query.p;
    await redisClient.set("test", data);
    res.status(200).json({
      message: "data cached",
      data: data,
    });
  } catch (err) {
    console.error(err);
    res.status(500).json({
      message: "Something went wrong",
    });
  }
});

app.get("/get", async (req, res, next) => {
  try {
    // const data = await redisClient.get("test");
    const data = await reddisClient.get("test").then((data) => {
      return data;
    });
    res.status(200).json({
      message: "Cached data retrieved",
      data,
    });
  } catch (err) {
    console.error(err);
    res.status(500).json({
      message: "Something went wrong",
    });
  }
});

app.listen(process.env.PORT || 3000, () => {
  console.log("Node server started");
});

请查看随附的输出屏幕截图。

所以最后的想法是,当我们使用回调并想要同步执行代码时,您应该在回调内部使用回调(但它会创建回调地狱,因此不再建议)或者您应该使用promise/async await/native nodejs 的 promisify 库。

请访问下面link以获得最简单的理解和示例。 https://docs.redis.com/latest/rs/references/client_references/client_nodejs/

希望我的问题能让你头脑清醒。我很高兴接受相关建议来改进答案。