如何正确的使用缓存,什么是缓存穿透

2020-10-19  本文已影响0人  singleZhang2010

什么是缓存穿透

看如下这个代码案例:

<?php
function getList($key)
{
  $list = $redis->get($key);//查询缓存
  if (!empty($list )) return $list ;
  $list = $this->getDb();//没有查询到缓存,从数据库中获取
  $redis->set($key,$list ,$time);//设置缓存
  return $list ;
}

上述案例中没有缓存穿透解决方案,在高并发下,如果缓存过期,会有多个请求到数据库,导致数据库崩溃。

如何解决?

<?php
function getList($key){
  $list = $redis->get($key);//查询缓存
  if (!empty($list))  return $list;
  $list= $this->getDb();//没有查询到缓存,从数据库中获取//如果缓存穿透后,数据库中没查询到数据,自定义数据,写入缓存
  if (empty($list)) $list = [];
  $redis->set($key,$list);
  return $list;
}

在缓存失效情况下,如果只想要一个请求到数据库中,该怎么处理

<?php
function getList($key){
  $data = $redis->get($key);//查询缓存
  if (!empty($data)) {
    //缓存未过期,返回数据
    if ($data['expireTime']>time()) return $data['data'];
    //缓存已过期,获取锁,如果未获取到锁,则返回过期数据
    if (!$redis->setNx()) return $data['data'];
  }
  $list = $this->getDb();//从数据库中获取

  if (empty($list)) $list = [];
  $expireTime = 120;//缓存时间为 120秒//设置过期时间
  $data = [
    'data'=>$list,
    'expireTime'=>$expireTime - 60
  ];
  $redis->set($key,$data,$expireTime);
  return $list;
}

上述方案可以解决缓存穿透,避免雪崩效应,加上锁机制,到达数据库的请求只有一个。
关于过期时间,使用我们自己的过期时间操作缓存数据有更大的灵活空间。缓存时间比我们业务定义的过期时间晚 60秒。这样,我们有60秒的时间刷新最新的数据到缓存数据库中。

上一篇下一篇

猜你喜欢

热点阅读