18、Hyperf 3 快速使用 - Hypref 3 缓存的使用

作者: 温新

分类: 【Hyperf 3 基础系列】

阅读: 624

时间: 2023-04-25 15:08:41

hi,我是温新,一名 PHPer

Hypref 版本:Hyperf 3.0

PHP 版本:PHP 8.2

系统版本:Rocky Linux 9.1

说明:

1、Hyperf 快速使用系列将全部在 Rocky Linux 9.1 中完成;

2、服务器、PHP 版本 等系列前置条件默认已符合;

3、Hyperf 中修改了代码需要重启 Hyperf 服务。文章中对此不再进行说明。

学习目标:掌握缓存的使用

hyperf/cache 提供了基于 Aspect 实现的切面缓存,也提供了实现 Psr\SimpleCache\CacheInterface 的缓存类。

安装

composer require hyperf/cache

配置

配置 默认值 备注
driver Hyperf\Cache\Driver\RedisDriver 缓存驱动,默认为 Redis
packer Hyperf\Utils\Packer\PhpSerializer 打包器
prefix c: 缓存前缀
<?php
// config/autoload/cache.php
return [
    'default' => [
        'driver' => Hyperf\Cache\Driver\RedisDriver::class,
        'packer' => Hyperf\Utils\Packer\PhpSerializerPacker::class,
        'prefix' => 'c:',
    ],
];

使用缓存

Hyperf 缓存默认使用 Redis 作为驱动。

方式一:通过 Simple Cache 方式

<?php

namespace App\Controller\Test;

use App\Model\User;
use Hyperf\DbConnection\Db;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Psr\Container\ContainerInterface;
use Psr\SimpleCache\CacheInterface;

#[Controller]
class UserController
{
    // 缓存实例对象
    protected $cache;
    
    public function __construct(ContainerInterface $container)
    {
        // 通过 Container 容器获取缓存实例对象
        $this->cache = $container->get(CacheInterface::class);
    }

    #[GetMapping('/users/index')]
    public function index(ResponseInterface $response)
    {
        $users = User::query()->where('id', '<', 5)->get();

        if ($this->cache->get('users')) {
            echo '获取缓存数据' . PHP_EOL;
            return $this->cache->get('users');
        }

        $this->cache->set('users', $users);
        return $users;
    }

   	// 删除缓存
    #[GetMapping('/users/del-cache')]
    public function delCache()
    {
        $res = $this->cache->delete('users');
        return ['result' => $res];
    }
}

方式二:通过注解使用缓存

添加缓存

组件提供 Hyperf\Cache\Annotation\Cacheable 注解,作用于类方法,可以配置对应的缓存前缀、失效时间、监听器和缓存组。

<?php
// App\Controller\Test\UserController.php
    
#[GetMapping('/users/{id}')]
#[Cacheable('user', '#{id}', 6000)]
public function getUserInfoById(int $id)
{
    echo '我会输出吗?';
    return User::query()->find($id);
}

在这个案例中,查询单个用户信息,当使用 Hyperf\Cache\Annotation\Cacheable 注解实现缓存时,会自动生成对应 key 的缓存。当没有缓存时,会设置缓存,当有缓存时,直接走缓存。因此,当有缓存时,我会输出吗? 不会在终端输出。

#{id} 会被解析为用户 ID 值。

在这个案例中,redis 中存储的 key 格式为:"c:user:3"

删除注解缓存

当有数据发生变化时,使用注解时如何删除缓存?可以通过监听器实现缓存的删除。

<?php
// App\Controller\Test\UserController.php

use Psr\EventDispatcher\EventDispatcherInterface;

#[Inject]
protected EventDispatcherInterface $dispatcher;

// 改动一下设置缓存的方法
// 这里添加一个监听器,删除缓存时用的就是这个监听器
#[GetMapping('/users/{id}')]
#[Cacheable('user', '#{id}', 6000, 'upser-cache-delete')]
public function getUserInfoById(int $id)
{
return User::query()->find($id);
}

#[GetMapping('/users/{id}/del-cache')]
public function delCacheByUserId(int $id)
{
    // DeleteListenerEvent 系统事件
    $this->dispatcher->dispatch(new DeleteListenerEvent('upser-cache-delete', ['id'=>$id]));

    return 'succ';
}

注解缓存学习

Cacheable

例如以下配置,缓存前缀为 user, 超时时间为 7200, 删除事件名为 USER_CACHE

当设置 value 后,框架会根据设置的规则,进行缓存 KEY 键命名。如下实例,当 $user->id = 1 时,缓存 KEYc:user:1

#[GetMapping('/users/lst/{id}')]
#[Cacheable(prefix:'user', ttl:60, listener:'USER_CACHE', value: "#{id}")]
public function getUserLst(int $id)
{
    $users = User::query()->where('id', '<', 5)->get();

    return [
        'users' => $users->toArray(),
        'uuid' => uniqid()
    ];
}

CacheAhead

缓存在规定时间内每隔多少时间进行初始化一次,直到缓存设置成功。

如:缓存前缀为 user, 超时时间为 7200, 生成对应缓存 KEY 为 c:user:1,并且在 7200 - 600 秒的时候,每 10 秒进行一次缓存初始化,直到首次成功。

#[CacheAhead(prefix: "user", ttl: 7200, aheadSeconds: 600, lockSeconds: 10, value:"#{id}")]
public function user(int $id): array
{
    $user = User::query()->find($id);

    return [
        'user' => $user->toArray(),
        'uuid' => uniqid(),
    ];
}

CachePut

CachePut 每次都会对缓存进行重写。如对缓存设置 60 秒过期,每刷新一次都会被重置为 60 秒。而 Cacheable 不同,设置超时时间为 60 秒后,无论怎么刷新,超时时间不会被重置。

#[GetMapping('/users/{id}')]
#[CachePut('user', '#{id}', 6000, 'upser-cache-delete')]
public function getUserInfoById(int $id)
{
return User::query()->find($id);
}

CacheEvict

CacheEvict 更容易理解了,当执行方法体后,会主动清理缓存。(实际上就删除指定的缓存)

#[GetMapping('/users/{id}/delete-cache')]
#[CacheEvict(prefix:'user', value: '#{id}')]
public function delUserCacheById(int $id)
{
    return $id;
}
请登录后再评论