对一些高频数据,我们都需要缓存起来,以免 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();