我是靠谱客的博主 迷你小蝴蝶,最近开发中收集的这篇文章主要介绍缓存穿透,大面积key失效的解决方案,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

缓存穿透,大面积key失效的解决方案

<?php
class cacheBreakdown
{
public $redis;
public $queueName
= 'queue_name';
public $error
= '';
public $surviveTime = 20;//存活时间,以秒计算
//总共有两种解决方案
queryCache
queryCache2
public function __construct() {
$this->redis = new redis();
}
/**
* 请求获取数据,缓存没有数据,则合并请求,发送一个请求到后台,防止击穿mysql服务
* @param $key
* @return bool|string
*/
public function queryCache($key) {
$res = $this->redis->get($key);
if (!empty($res)) {
return $res;
}
$lock = $this->joinTheQueue($key);
usleep(200000);//200毫秒
return $this->queryCache($key);
}
/** 第二种方案
* @param $key
* @return bool|string
*/
public function queryCache2($key) {
$res = $this->redis->get($key);
if (!empty($res)) {
return $res;
}
$lock = $this->getLock($key);
if (!$lock) {
usleep(200000);//200毫秒
return $this->queryCache2($key);
}
//去数据库查询数据,然后返回
//去数据库查询
$res = db::query('select * from order where id = '.$key);
$this->setCache($key, $res);
$this->unlock($lock);
return $res;
}
/**
* 上锁
* @return bool|resource
*/
public function getLock($key) {
$file_name = 'lock.data'.$key;
if (!file_exists($file_name)) {
file_put_contents($file_name, 0);
}
$fp
= fopen($file_name, 'r');
$res = flock($fp, LOCK_EX);
if ($res) {
return $fp;
} else {
return $res;
}
}
/**
* 释放锁
* @param $fp
* @return bool
*/
public function unlock($fp) {
flock($fp, LOCK_UN);
return fclose($fp);
}
/**
* 加入唯一队列
* @param $key
* @return int
*/
public function joinTheQueue($key) {
$s_res = $this->redis->sAdd($key, 1);
if ($s_res) {
$res
= $this->redis->lPush($this->queueName, $key);
$this->error = '队列没有该值,加入队列排队,结果为:'.$res;
return $res;
}
$this->error = '队列有该值';
return 99;
}
/**
* 消费队列,拿出数据,存入缓存
*/
public function consumptionQueue() {
while (true) {
$key = $this->redis->rPop($this->queueName);
if (empty($key)) {
usleep(200000);//200毫秒
continue;
}
//去数据库查询
$res = db::query('select * from order where id = '.$key);
return $this->setCache($key, $res);
}
}
/**
* 设置值
* @param $key
* @param $value
* @return bool
*/
public function setCache($key, $value) {
$time = rand(0, 9);
//防止大面积key同时失效
$time = $this->surviveTime + $time;
return $this->redis->setex($key, $time, $value);
}
}

最后

以上就是迷你小蝴蝶为你收集整理的缓存穿透,大面积key失效的解决方案的全部内容,希望文章能够帮你解决缓存穿透,大面积key失效的解决方案所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部