一个基于thinkphp,redis的缓存工具管理类
对应的数据表
CREATE TABLE `cy_cache` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tag` char(32) NOT NULL COMMENT 'tag号',
`key` text NOT NULL COMMENT '生成的缓存的键',
`table` varchar(40) NOT NULL DEFAULT '' COMMENT '该条缓存记录所涉及的表',
`table_pk_id` int(11) NOT NULL DEFAULT '0' COMMENT '所关联的表的pkid',
`md5_key` char(64) NOT NULL COMMENT 'TP_CACHE层面对应md5',
`update_at` int(11) NOT NULL COMMENT '更新时间',
`expire` int(11) NOT NULL COMMENT '缓存的有效期',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5386 DEFAULT CHARSET=utf8mb4 COMMENT='基于具体业务的缓存管理表';
缓存设置类
class CyCacheSet
{
public const APP_COMPANY_LIST = "APP_COMPANY_LIST"; //公司列表
public const APP_EVENT_LIST = "APP_EVENT_LIST"; //事件列表
public const APP_INVESTOR_LIST = "APP_INVESTOR_LIST"; //投资人列表
public const APP_FOUNDER_LIST = "APP_FOUNDER_LIST"; //创业者列表
public const APP_CAPITAL_LIST = "APP_CAPITAL_LIST"; //投资机构列表
public const APP_COMPANY = "APP_COMPANY"; //公司
public const APP_EVENT = "APP_EVENT"; //事件
public const APP_INVESTOR = "APP_INVESTOR"; //投资人
public const APP_FOUNDER = "APP_FOUNDER"; //创业者
public const APP_CAPITAL = "APP_CAPITAL"; //投资机构
public const APP_PROJECT_HOME = "APP_PROJECT_HOME"; //投资机构
public const APP_NEWS_STATION_HOME = "APP_NEWS_STATION_HOME"; //投资机构
public const APP_RECOMMEND_API = "APP_RECOMMEND_API"; //投资机构
public static $keyDescMaps = [
self::APP_COMPANY_LIST => '公司列表',
self::APP_EVENT_LIST => '事件列表',
self::APP_INVESTOR_LIST => '投资人列表',
self::APP_FOUNDER_LIST => '创业者列表',
self::APP_CAPITAL_LIST => '投资机构列表',
self::APP_COMPANY => '公司',
self::APP_EVENT => '事件',
self::APP_INVESTOR => '投资人',
self::APP_FOUNDER => '创业者',
self::APP_CAPITAL => '投资机构',
self::APP_PROJECT_HOME => "创投首页",
self::APP_NEWS_STATION_HOME => '新闻站',
self::APP_RECOMMEND_API => 'app推荐列表',
];
/**
* tag值
* @var string
*/
public $tag = '';
/**
* 缓存的key值
* @var string
*/
public $key = '';
/**
*设计的相关的表
* @var array
*/
public $table = '';
/**
* 涉及的表的相关的主键
* @var
*/
public $tablePkId = 0;
/**
* 缓存时间0表示永久缓存
* @var
*/
public $expire = 0;
public $cacheRule = 1;//缓存的策略,1表示在读取缓存失败的时候,会获取后重新设置缓存,几乎适用于所有场景
/**
* @var string Yii里面的dependence类,这是一个SQL语句,以后根据情况看看是否有必要参考Yii的使用
* select max(update_at) from xxx where xxx;
*/
public $dependence = "";
/**
* 获取缓存的key
* @return string
*/
public function getStoreKey()
{
return md5($this->key);
}
/**
* 获取缓存时间
* @return int
*/
public function getExpire()
{
return $this->expire <= 0 ? $this->expire : $this->expire + rand(0,60);
}
/**
* 返回更新时间
* @return int
*/
public function checkDependence()
{
if ($this->dependence){
try{
$result = Db::query($this->dependence);
$updatedAt = $result[0]['updated_at'];
return $updatedAt;
}catch (\Exception $exception){
return -1;
}
}
return -1;
}
/**
* 获取依赖的key
* @return string
*/
public function getDpStoreKey()
{
return $this->getStoreKey()."_updated_at";
}
}
数据表模型
/**
* Class ZipArchive
* @package app\common\helper
*/
class CyCacheModel extends BaseModel
{
protected $name = 'cy_cache';
}
缓存工具类
/**
* 缓存管理工具类
* Class CyCacheTool
* @package app\common\lib\cycache
*/
class CyCacheTool
{
protected static $instance = null;
protected $dbModel = null;
protected $tpCache = null;
private function __construct()
{
$this->dbModel = new CyCacheModel();
$this->tpCache = new Cache();
}
public static function getInstance()
{
if (is_null(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
protected function setCache(callable $callBack, CyCacheSet $cacheSet)
{
$result = call($callBack);
//小于0表示不缓存
if ($cacheSet->expire < 0 ){
return $result;
}
if (!$cacheSet->key) {
exception('缓存的key不能为空');
}
if ($result) {
//实际设置的有效时间由一定范围波动
$this->tpCache->tag($cacheSet->tag)
->set($cacheSet->getStoreKey(), $result, $cacheSet->getExpire());
$where = [
['table', '=', $cacheSet->table],
['table_pk_id', '=', $cacheSet->tablePkId],
['tag', '=', $cacheSet->tag],
['md5_key', '=', $cacheSet->getStoreKey()],
];
$this->dbModel->where($where)->delete();
$this->dbModel->createOne([
'tag' => $cacheSet->tag,
'key' => $cacheSet->key,
'table' => $cacheSet->table,
'table_pk_id' => $cacheSet->tablePkId,
'md5_key' => $cacheSet->getStoreKey(),
'update_at' => time(),
'expire' => $cacheSet->expire,
]);
}
return $result;
}
public function getCache(callable $callBack, CyCacheSet $cacheSet)
{
$data = $this->tpCache->tag($cacheSet->tag)
->get($cacheSet->getStoreKey());
$updatedAt = $cacheSet->checkDependence();
$depCond = false;
if ($updatedAt >=0 && $updatedAt > $this->tpCache->get($cacheSet->getDpStoreKey()) ){ //表示依赖条件起作用
$depCond = true;
}
if (!$data && ($cacheSet->cacheRule == 1|| $depCond == false )) {
$data = $this->setCache($callBack, $cacheSet);
}
if ($updatedAt>0){
$this->tpCache->set($cacheSet->getDpStoreKey(),$updatedAt,3600);
}
return $data;
}
/**
* 删除和某个表相关的缓存
* @param string $table
* @param string $pkId
*/
public function deleteCacheByTable($table = '',$pkId = '')
{
if (!$table){
return;
}
$where[]= ['table','=',$table];
if (!is_null($pkId)){
$where[] = ['table_pk_id','=',$pkId];
}
$cacheKeys = $this->dbModel->where($where)->column('md5_key');
foreach ($cacheKeys as $cacheKey){
$this->tpCache->rm($cacheKey);
}
$this->dbModel->where($where)->delete();
}
/**
* 按照标签清除缓存
* @param $tag
*/
public function deleteCacheByTag($tag = '')
{
if ($tag) {
$this->dbModel->where('tag', '=', $tag)->delete();
$this->tpCache->clear($tag);
}
}
/**
* 根据具体的一个缓存的键删除缓存
* @param $cacheKey
*/
public function deleteCacheByKey($cacheKey)
{
if (!is_array($cacheKey)) {
$cacheKey = [$cacheKey];
}
foreach ($cacheKey as $value){
$this->tpCache->rm($value);
}
$this->dbModel->where("md5_key","in",$cacheKey)->delete();
}
}
使用案例
$cacheKey = "1231";//自己根据业务设置,保证不重复就行
$cacheSet = new CyCacheSet();
$cacheSet->expire = 600;
$cacheSet->key = $cacheKey;
$cacheSet->table = 'content';//涉及的表明
$cacheSet->tablePkId = $contentId;//表的主键
$cacheSet->tag = CyCacheSet::APP_CAPITAL;//标签
$data = CyCacheTool::getInstance()->getCache(function () use ($contentId) {
//业务逻辑代码
return $realData;
}, $cacheSet);
//如果设置了缓存的标签,或者表名和id。就可以在需要触发调用删除缓存的地方,调用对应的delele方法定向删除.