PHP缓存穿透及使用Redis进行缓存加锁的方法

这篇文章主要介绍“PHP缓存穿透及使用redis进行缓存加锁的方法”,在日常操作中,相信很多人在PHP缓存穿透及使用Redis进行缓存加锁的方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”PHP缓存穿透及使用Redis进行缓存加锁的方法”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

站在用户的角度思考问题,与客户深入沟通,找到景宁畲族自治网站设计与景宁畲族自治网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:网站建设、成都网站制作、企业官网、英文网站、手机端网站、网站推广、空间域名、虚拟主机、企业邮箱。业务覆盖景宁畲族自治地区。

一 缓存穿透

缓存穿透指的是,当我们访问某个缓存KEY想取得对应的数据时,若此KEY不存在于缓存中,则会去查库。如何解决呢?将每次查询的结果都放入缓存不管是不是空。

public function getArticles($key){$expire = 60 * 3;$data = Cache::get($key);//注意:此处使用is_null来判断而不是直接使用 (!$data)来判断。    //使用 (!$data)来判断的弊端是:如果$data的值为空字符串或者空数组,此处也是不成立的,会继续执行查询DB的语句,造成缓存穿透    if (!is_null($data)) {return $data;}$data = $this->searchDB();Cache::put($key, $data, $expire);return $data;}

这样处理的原因是,即使当前查询的key为空字符串,或者空数组,结果也会被缓存起来。当下一次访问时会直接返回,不会造成缓存穿透

二 缓存加锁(Redis)

若系统的并发很高,当缓存过期时,则大量的请求会穿透缓存,同时到DB中查询,那我们可以设置缓存当缓存过期时,只去DB中请求一次并缓存吗?可以,我们可以使用redis的setNx()
setNx($key) 的作用类似于set($key) ,setNx的意思为 set Not Exists 如果$key不存在则设置,存在则不进行任何操作. 设置成功设置返回1,说明当前的请求获得了当前的操作权限,设置失败返回0,说明此资源已经被其他请求获得。使用代码实现的话,思路如下:

  1. 给存入缓存的数据增加一个过期时间字段暂时给这个字段起名字叫$data['expire'](这个过期时间要短于实际的缓存过期时间),方便在缓存过期前执行加锁和缓存更新。

  2. 如果$data['expire']达到过期时间,则执行加锁以及缓存更新。

  3. 此时如果有其他请求进入则返回更新之前的数据。

代码如下:

public function getArticlesLock($key){$time = time();$expire = 10 * 2;$lockKey = 'lock:k';$data = Cache::get($key);if (!is_null($data)) {//缓存未过期        if ($data['expire'] > time()){return $data['data'];}//加锁失败说明已经有请求执行加锁,返回之前的缓存数据        if (!Redis::setnx($lockKey,1)) {return $data['data'];}}sleep(3);$datat = $this->searchDB();$data = ['data' => $datat,'expire' => $time + $expire - 10];$r = Cache::put($key, $data, $expire);//解锁    Redis::del($lockKey);return $data['data'];}

当然此处也可以使用set()来代替setnx()加锁,以及使用lua脚本解锁。

到此,关于“PHP缓存穿透及使用Redis进行缓存加锁的方法”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注创新互联网站,小编会继续努力为大家带来更多实用的文章!


名称栏目:PHP缓存穿透及使用Redis进行缓存加锁的方法
本文URL:http://pwwzsj.com/article/pcdcgj.html