【问题标题】:redis connection factory - will this cause memory leaks?redis 连接工厂 - 这会导致内存泄漏吗?
【发布时间】:2021-02-12 01:47:15
【问题描述】:

希望有人能给我一些建议

我创建了一个模块,它基本上使用单例模式创建了一个 redis 连接,该模式也使用了 Promise。

但是,在我返回 redis 连接之前,我首先检查连接是否准备好,在 ready 事件上,我解决了 Promise,同样,如果出现任何错误,我会拒绝 Promise。

我唯一关心的是这种方法,我是否可以在监听器功能就绪时引入内存泄漏,并且在承诺完成后错误可能会继续监听,应该由垃圾收集器清理。

我不确定这是否会造成某种内存泄漏..

任何建议将不胜感激。

从'redis'导入redis; 从'redis-redisearch'导入redisearch; 重新搜索(redis); 让 redisClient: redis.RedisClient = null; 导出函数 getRedisClient(): Promise { return new Promise((resolve: any, reject: any) => { if (redisClient && redisClient.connected) { 返回解析(redisClient); } redisClient = redis.createClient({ 密码:process.env.REDIS_PASSWORD, 重试策略:功能(选项){ if (options.error && options.error.code === "ECONNREFUSED") { // 在特定错误上结束重新连接并刷新所有命令 // 单个错误 return new Error("服务器拒绝连接"); } 如果 (options.total_retry_time > 1000 * 60 * 60) { // 在特定超时后结束重新连接并刷新所有命令 // 有一个单独的错误 return new Error("重试时间用完"); } if (options.attempt > 10) { // 以内置错误结束重新连接 返回未定义; } // 之后重新连接 返回 Math.min(options.attempt * 100, 3000); }, }); redisClient.on("ready", function (error: any) { console.log("连接良好"); 返回解析(redisClient); }); redisClient.on("error", function (error: any) { console.log("拒绝错误"); 如果(redisClient){ redisClient.end(false); redisClient = null; 返回拒绝(错误); } }); }) }

【问题讨论】:

    标签: javascript typescript redis node-redis


    【解决方案1】:

    如果在任何redisClients 完成连接之前多次调用getRedisClient,则此模式可以创建多个redisClients。一个稍微简单的模式可能是缓存 Promise<RedisClient> 而不是 redisClient

    let redisClientP: Promise<RedisClient>;
    function getRedisClient (): Promise<RedisClient> {
      if (redisClientP) return redisClientP;
      redisClientP = new Promise(...previous code)
      return redisClientP;
    }
    

    如果您以前没有见过这种缓存的Promise 用法,这里有一个小sn-p 演示您可以多次访问Promise 上的.then

    const p = new Promise((resolve) => resolve(2));
    
    
    (async function main () {
      for (let i = 0; i < 100; i++) {
        console.log(i, await p); 
      }
    })()
    

    【讨论】:

    • 感谢Willis 的回复,但是如果我缓存一个promise 并再次调用它,它将不再响应?根据我的理解,一个承诺只能解决一次
    • 一个promise 只能resolve 一次,但它可以多次调用.then 并且.then 的每个调用者都将被赋予resolve 值。这有意义吗?我编辑添加了另一个示例来演示该概念。一个承诺归结为一个模糊的对象,如{then: () =&gt; resolvedValue, cache: () =&gt; thrownValue}
    • 非常感谢,这是有道理的 :)) 不过我还是有点困惑,如果 redisClient 关闭并且我总是得到相同的 Promise,我将永远无法获得新的连接,如果Redis 连接已断开或已死?还是我错过了什么?
    • 你完全理解:如果redis客户端关闭了,可以设置redisClientP = null重新创建(老的redis客户端因为有监听器,不会被垃圾回收),也可以依赖保持连接的重试逻辑。我通常会设置一个客户端来连接到数据库,并依靠该客户端的连接逻辑来维护该连接。如果连接到数据库时出现问题,重新创建客户端可能没有帮助。
    • 你太棒了,非常感谢你的帮助 :).. 所以最终,我不需要复杂性,我应该只使用一个连接并保留它.. 我想我会这样做:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多