简体   繁体   English

NodeJS Redis - 在后台重新连接

[英]NodeJS Redis - Reconnect In Background

The situation I have is - I am trying to retrieve a resource through REDIS key.我的情况是 - 我正在尝试通过 REDIS 密钥检索资源。 If the key isn't present, then get it from an API.如果密钥不存在,则从 API 获取它。

Running into an issue where if the Redis connection dies or if I cannot connect to Redis from startup, then the nodejs library ('redis') will just continue to try to reconnect.遇到一个问题,如果 Redis 连接中断,或者我无法从启动时连接到 Redis,那么 nodejs 库 ('redis') 将继续尝试重新连接。 And it is blocking me from getting the information I need through the API, as the retry logic will take over and will not continue on getting the needed information.它阻止我通过 API 获取我需要的信息,因为重试逻辑将接管并且不会继续获取所需的信息。

I would like this functionality running in the background - is it possible?我希望此功能在后台运行 - 可能吗?

Meaning, if Redis is down/cannot connect to REDIS from NodeJs, then it will try to reconnect.意思是,如果 Redis 关闭/无法从 NodeJs 连接到 REDIS,那么它将尝试重新连接。 However, while it is down and the app will try to periodically reconnect, I want to be able to get the data through the backup plan ie through the API, as I mentioned above.但是,当它关闭并且应用程序将尝试定期重新连接时,我希望能够通过备份计划(即通过 API)获取数据,如上所述。

Any pointers on this situation would be greatly appreciated - thank you in advance.任何关于这种情况的指示将不胜感激 - 在此先感谢您。

You could create a wrapper/proxy around your redis-connection where you make sure that redis is connected for all the redis operations.您可以在 redis-connection 周围创建一个包装器/代理,以确保 redis 已连接到所有 redis 操作。 If not you can either throw an error (which you can handle in the caller) or return undefined.如果不是,您可以抛出错误(您可以在调用者中处理)或返回未定义。

Basically you can listen for the ready and error events and update a status -flag inside that wrapper in order to always know the current connection status.基本上,您可以侦听readyerror事件并更新该包装器内的status标志,以便始终了解当前的连接状态。

Now, this will certainly cover the case when the initial connection is not successful or when a disconnect happens between calls.现在,这肯定会涵盖初始连接不成功或呼叫之间发生断开连接的情况。 The problem are the rare cases where the disconnect happens after you checked the status -flag successfully.问题是在您成功检查status标志后发生断开连接的罕见情况。 To tackle this you could define a max wait time for the redis call and return/throw an error if that timeout is reached and ignore the redis result.为了解决这个问题,您可以定义 redis 调用的最大等待时间,并在达到超时时返回/抛出错误并忽略 redis 结果。 Here's some basic code which might help you get started:以下是一些基本代码,可以帮助您入门:

class RedisService {
    isConnected = false;
    client;

    constructor() {
        this.client = redis.createClient();
        this.client.get = promisify(this.client.get).bind(this.client);
        this.client.set = promisify(this.client.set).bind(this.client);
        this.attachHandlers();
    }

    attachHandlers() {
        this.client.on("ready", () => {
            this.isConnected = true;
        });           
        this.client.on("error", (err) => {
            this.isConnected = false;
            console.log(err);
        });
    }

    async tryGet(key) {
        if (!this.isConnected) {
            return undefined; // or throw an error
        }
        return Promise.race([this.client.get(key), this.wait()]);
    }

    async trySet(key, val) {
        if (!this.isConnected) {
            return undefined; // or throw an error
        }
        return Promise.race([this.client.set(key, val), this.wait()]);
    }

    wait(ms = 200) {
        return new Promise(resolve => {
            setTimeout(resolve, ms);
        })
    }
}

Then in your caller you can do:然后在您的来电者中,您可以执行以下操作:

async someMethodThatCallsRedisOrApi() {
    let result;
    try {
        result = await redisService.tryGet('testkey');
    } catch (e) {
        console.log(e);
    }
    if (!result) {
        result = apiService.get(...); // call the actual api to get the result
        await redisService.trySet('testkey', result);
    }
    res.json(result)
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM