可复用的缓存组件

Laravel框架
649
0
0
2022-05-16

对一些高频数据,我们都需要缓存起来,以免 MySQL 压力过大。

一般的写法是先判断缓存中是否有数据,没有数据再将数据查出来,再缓存起来。

其实可以用一个函数将这个过程封装起来

helper.php

if (!function_exists('remember')) {
    /**
     * 缓存数据
     *
     * @param $uniqId
     * @param $dataSource mixed|\Closure 数据来源
     * @param int $ttl
     * @return mixed|string
     */ 
    function remember($uniqId, $dataSource, int $ttl = 600)
    {
        $redisKey = 'remember:' . $uniqId;
        $result = Redis::get($redisKey);

        if ($result) {
            return unserialize($result);
        }

        if ($dataSource instanceof \Closure) {
            $result = $dataSource();
        } elseif (is_array($dataSource) && isset($dataSource[0]) && is_object($dataSource[0])) {
            $object = $dataSource[0];
            $function = $dataSource[1];
            $args = $dataSource[2] ?? [];
            $result = call_user_func_array([$object, $function], $args);
        } else {
            $result = $dataSource;
        }

        Redis::setex($redisKey, $ttl, serialize($result));
        return $result;
    }
}
if (!function_exists('forget')) {
  /**
 * 清除已缓存的数据
  *
 * @param $uniqId
  * @return int
 */  function forget($uniqId): int{
  $redisKey = 'remember:' . $uniqId;
 return Redis::del($redisKey);
  }
}

使用方法

$linkData = remember("player_link_data:{$gid}:{$uid}", function () use ($gid, $uid) {
                $player = Player::whereUid($uid)->whereGid($gid)->first();
                return [
                    'admin_id' => $player->admin_id,
                    'team_id' => $player->team_id,
                ];
            });

缓存对象执行某个方法后的结果

除了可以将回调函数的执行结果缓存,还可以将对象执行某个方法后的结果缓存起来

app/Services/Cache/CacheBase.php

<?php

namespace App\Services\Cache;

use Illuminate\Support\Arr;

abstract class CacheBase
{
    /**
     * 全部数据
     * @var array
     */ 
    protected array $all;

    /**
     * 缓存的唯一 id
     * @var string
     */ 
    protected string $uniqid;

    protected int $ttl = 600;

    /**
     * 获取全部数据
     * @return array
     */ 
    abstract protected function allData(): array;

    /**
     * 获取全部数据并缓存
     * @return mixed|string
     */ 
    public function all()
    {
        $all = remember($this->uniqid, [$this, 'allData'], $this->ttl);
        return $all;
    }

    /**
     * 清除数据缓存
     * @return int
     */ 
    public function clean()
    {
        return forget($this->uniqid);
    }

    public function get($key)
    {
        $all = $this->all();
        $result = $all[$key] ?? null;

        return $result;
    }

    public function only($keys)
    {
        $all = $this->all();
        $result = Arr::only($all, $keys);

        return $result;
    }

    public function __get($property)
    {
        if (!isset($this->all)) {
            $this->all = $this->all();
        }

        $result = $this->all[$property] ?? null;

        return $result;
    }
}

app/Services/Cache/User/BanIpList.php

<?php

namespace App\Services\Cache\User;

use App\Models\Config\BanIp;
use App\Services\Cache\CacheBase;

class BanIpList extends CacheBase
{
    protected string $uniqid;

    public function __construct()
    {
        $this->uniqid = 'BannedIp:';
    }

    public function allData(): array{
        return BanIp::where('release_time', '>', BanIp::raw('now()'))
            ->where('enable', '=', 1)
            ->pluck('ip')->toArray();
    }
}
use App\Services\Cache\User\BanIpList;

$banIPObj = new BanIpList();
$banIPList = $banIPObj->all();