thinkphp 缓存管理类

一个基于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方法定向删除.
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,753评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,668评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,090评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,010评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,054评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,806评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,484评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,380评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,873评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,021评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,158评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,838评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,499评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,044评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,159评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,449评论 3 374
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,136评论 2 356

推荐阅读更多精彩内容