使用场景
: 对于量级小,常用的基础数据做内存缓存,提高运算速度
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的性能优势
利用事件监听能力,很方便就能处理缓存击穿的问题