使用缓存提高性能
前段时间和北京领养日合作,粉丝有六位数,担心服务器扛不住,向大佬请教服务器相关,大佬提了建议使用缓存,于是研究了一番。
缓存模式
Cache Aside模式
- 同时更新数据库和缓存
具体实现:
- 命中: 从缓存中取数据,成功后返回数据
- 更新: 更新数据库,成功后使缓存失效
- 失效: 从缓存中取数据,失败则从数据库取数据,并放入缓存
存在的问题:
两个并发操作,一个读操作,没有命中缓存就到数据库中读取数据;另一个写操作,更新数据库,使缓存失效,之前的读操作会把读到的老数据放入缓存。
当然以上也是概率比较低的情况,写操作会比读操作慢的多,而读操作要早于写操作前进入数据库操作,又要晚于写操作更新缓存。
Read/Write Through模式
- 先更新缓存,缓存同步更新数据库
Write Behind Caching模式
- 先更新缓存,缓存定时异步更新数据库
Code Time
// get
try {
const cache = fs.readFileSync('cacheFile', 'utf8')
const temp = JSON.parse(cache)
// 缓存结构为{"data": [], "expireTime": time}
const expireTime = temp.expireTime
const now = moment().unix()
// 有缓存但已过期
if (now > Number(expireTime)) {
data = await mysql.query(sql)
// 写入缓存
setDataCache(fileName, data)
} else {
// 有缓存且没过期
data = temp.data
}
} catch (err) {
// 没有缓存文件,获取数据并写入缓存
data = await mysql.query(sql)
setDataCache(fileName, data)
}
function setDataCache (fileName,data) {
// 设置缓存过期时间
const expireTime = moment().add(2, 'hours').unix()
const cacheData = {
data,
expireTime
}
// 将数据写入文件用作缓存
fs.writeFile(path.resolve(cachePath, fileName), JSON.stringify(cacheData), err => {
if (err) throw err;
})
}
// update
// 先更新数据库
await mysql.query(sql)
// 再删除缓存
try {
fs.unlink('cacheFile', err => {
if (err) throw err
})
}
经过这么一番操作,首页接口速度已由一百多ms降到几十ms,我那279元三年的服务器松了一口气~
参考:左耳朵耗子《性能设计篇之”缓存”》