在node中实现高效缓存

使用场景: 对于量级小,常用的基础数据做内存缓存,提高运算速度

getRegionCache方法不仅对外输出,同时内部计算也会使用,为了保证高效,需要隐性异步,不能直接声明async

初始化缓存

返回Promise 同步等待

function getRegionCache(key) {
  if (!cache) {
    return new Promise(resolve => {
      reflashCache().then(() => {
        resolve(cache.get(key))
      });
    });
  }
}

调用者拿到的是Promise对象,直接await即可

async getRegionCacheAPI(key) {
    return await getRegionCache(key)
}

缓存异步刷新

  • 对于这类基础数据的缓存,低实时性,通过自维护方式失效,类似LRU的实现

缓存到失效时间后通过process.nextTick放入微任务队列异步刷新, 同步计算先拿旧数据继续执行

function getRegionCache(key) {
  if (overTime) {
    process.nextTick(() => reflashCache());
    updateCacheTime = Date.now();
  }
  return cache.get(key);
}

缓存击穿

  • 在缓存初始化和失效时,大量并发请求同时触发缓存刷新,严重影响数据库性能

通过设置once事件监听缓存刷新完成,待缓存刷新结束后,依次返回结果,避免并发刷新缓存

const event = new events.EventEmitter();
event.setMaxListeners(100); //注意设置监听者数量,超过数量会触发leak memory告警

await reflashCache() {
  await new Promise(async resolve => {
    event.once('finish', resolve);
    if (eventStatus === 'ready') {
      eventStatus = 'pending';
      }
      event.emit('finish');
      eventStatus = 'ready';
    }
  });
}

总结

通过将数据库查询任务放入异步队列,避免了运算时同步等待,体现出node的性能优势

利用事件监听能力,很方便就能处理缓存击穿的问题

你可能感兴趣的:(在node中实现高效缓存)