美文网首页
Node使用redis库链接数据库,如何在数据库断开时跳过查询

Node使用redis库链接数据库,如何在数据库断开时跳过查询

作者: 平仄_pingze | 来源:发表于2018-02-10 20:58 被阅读131次

    一句话,redis实例方法都会返回boolean值,表示当前服务是否可用。这个值更新不及时时,就会在回调中返回err。

    背景

    今天老司机提了这个问题。像下面的代码

    // redis v2.8.0
    const redis = require('redis');
    const rdb = redis.createClient();
    
    rdb.on('error', err => console.error('全局捕获', err));
    
    ......
    rdb.get(key, (err, ret) => {
      if (err) console.log('局部捕获', err)
    });
    

    如果程序执行中,Redis server断开了,全局会捕获到错误,rdb.get()中的回调根本执行不到。
    那么如果希望,server断开时,rdb.get()取不到的情况下,可以取一个默认值,而不是一直卡着,怎么做呢?
    npm上似乎没有找到判断的方法。

    阅读redis源码,有这么一段:

    RedisClient.prototype.internal_send_command = function (command_obj) {
      ......
      if (this.ready === false || this.stream.writable === false) {
        ......
        return false;
      }
    }
    

    这个原型函数,就是执行redis实例方法时,最后的返回。可以看到,redis内部维持了一些状态量,表示服务是否可用;不可用时,方法直接返回false。

    原来redis库内部默认设置自动重连时,会不断检查和重置this.ready状态。

    但是,经过高频启动和关闭server测试,这个状态当然不是即时改变的。当查询时,如果this.ready=true但服务已经关了,就会抛出错误,好在这是可以在回调函数中捕获的。

    最佳实践

    function get(key) {
      return new Promise((resolve, reject) => {
        const isAvailable = rdb.get(key, (err, ret) => {
          if (err) {
            if (err.code === 'UNCERTAIN_STATE') return resolve(false);
            return reject(err);
          }
          resolve(ret);
        });
        if (!isAvailable) return resolve(false);
      });
    }
    
    ~async function () {
      let val = await get(key);
      if (val === false) {
        // 说明数据库断开,查询失败
      }
    }();
    

    相关文章

      网友评论

          本文标题:Node使用redis库链接数据库,如何在数据库断开时跳过查询

          本文链接:https://www.haomeiwen.com/subject/gcshtftx.html