使用场景
: 对于量级小,常用的基础数据做内存缓存,提高运算速度
getRegionCache
方法不仅对外输出,同时内部计算也会使用,为了保证高效,需要隐性异步,不能直接声明async
初始化缓存
返回Promise 同步等待
1 2 3 4 5 6 7 8 9
| function getRegionCache(key) { if (!cache) { return new Promise(resolve => { reflashCache().then(() => { resolve(cache.get(key)) }); }); } }
|
调用者拿到的是Promise对象,直接await即可
1 2 3
| async getRegionCacheAPI(key) { return await getRegionCache(key) }
|
缓存异步刷新
- 对于这类基础数据的缓存,低实时性,通过自维护方式失效,类似LRU的实现
缓存到失效时间后通过process.nextTick
放入微任务队列异步刷新, 同步计算先拿旧数据继续执行
1 2 3 4 5 6 7
| function getRegionCache(key) { if (overTime) { process.nextTick(() => reflashCache()); updateCacheTime = Date.now(); } return cache.get(key); }
|
缓存击穿
- 在缓存初始化和失效时,大量并发请求同时触发缓存刷新,严重影响数据库性能
通过设置once事件监听缓存刷新完成,待缓存刷新结束后,依次返回结果,避免并发刷新缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const event = new events.EventEmitter(); event.setMaxListeners(100); await reflashCache() { await new Promise(async resolve => { event.once('finish', resolve); if (eventStatus === 'ready') { eventStatus = 'pending'; } event.emit('finish'); eventStatus = 'ready'; } }); }
|
总结
通过将数据库查询任务放入异步队列,避免了运算时同步等待,体现出node的性能优势
利用事件监听能力,很方便就能处理缓存击穿的问题