使用缓存提高性能

Author Avatar
jiandandkl 3月 18, 2019
本文总阅读量
  • 在其它设备中阅读本文章

前段时间和北京领养日合作,粉丝有六位数,担心服务器扛不住,向大佬请教服务器相关,大佬提了建议使用缓存,于是研究了一番。

缓存模式

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元三年的服务器松了一口气~

参考:左耳朵耗子《性能设计篇之”缓存”》