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方法定向删除.

你可能感兴趣的:(thinkphp 缓存管理类)