symfony7之使用redis缓存
- 部分代码如下
//这个是 redis cache servvice 的部分定义
public function get(CachePrefixEnum $prefix, string $hashKey): mixed
{
$key = $this->buildCacheKey($prefix, $hashKey);
$item = $this->cache->getItem($key);
return $item->isHit() ? $item->get() : null;
}
- 然后在使用的时候,有这么一个定义
$statisticsDto = $this->cacheService->get(Enum\CachePrefixEnum::EVENT_STATS, $hashKey);
if ($statisticsDto instanceof Dto\Query\Statistic\EventStatisticsDto) {
$announcedEventsDto = $statisticsDto->getAnnouncedEvents();
} else {
//other logic
}
- 问题是对于拿到的redis缓存数据,为什么可以用
instanceof? 原因如下:
1. 缓存的是一个对象(例如 EventStatisticsDto 实例)。
2. Redis 缓存实际上存储的是序列化后的字符串(二进制数据)。
3. Symfony 的缓存组件在底层会帮你自动做序列化和反序列化操作。
4. 取缓存时 $item->get() 返回的就是你缓存时存进去的原始对象(经过自动反序列化后的对象)。
- 实际上直接使用
redis缓存数据是不可能有这个instanceof的
1. Redis 里缓存的是序列化后的字符串,不是对象本身。
2. Symfony 缓存组件(symfony/cache)会自动对数据做序列化和反序列化,所以 $item->get() 返回的才是反序列化后的对象实例。
3. 如果绕过了 Symfony 缓存组件,直接用 Redis 客户端取数据(原始字符串)时,确实没法 instanceof,因为它就是字符串,不是对象。
现在深入分析一下symfony7的缓存策略
- 通过 Symfony 缓存组件 API 来操作缓存(CacheItemPoolInterface),而不是直接使用redis命令操作.
- 关于 CacheItemPoolInterface 的解释如下
- 它是 PSR-6 缓存接口规范里定义的一个核心接口。
- 用于定义缓存池(Cache Pool)的行为。
- Symfony 的缓存组件实现了这个接口(如 Symfony\Component\Cache\Adapter\RedisAdapter),以标准方式操作缓存项。
- 主要职责和作用
- 获取缓存项(key 对应的缓存数据项)。
- 保存缓存项(更新或新建缓存数据)。
- 删除缓存项。
- 清空缓存池。
- 批量操作。
- 核心方法
interface CacheItemPoolInterface { // 根据缓存键获取缓存项对象 CacheItemInterface public function getItem(string $key): CacheItemInterface; // 获取多个缓存项对象 public function getItems(array $keys = []): iterable; // 检查缓存键是否存在且未过期 public function hasItem(string $key): bool; // 保存缓存项(写入缓存) public function save(CacheItemInterface $item): bool; // 延迟保存缓存项(可以批量写入) public function saveDeferred(CacheItemInterface $item): bool; // 提交所有延迟保存的缓存项 public function commit(): bool; // 删除指定缓存项 public function deleteItem(string $key): bool; // 删除多个缓存项 public function deleteItems(array $keys): bool; // 清空整个缓存池 public function clear(): bool; } - 之前的get()方法与 CacheItemInterface 的关系
getItem($key) 返回一个 CacheItemInterface 对象,代表具体的缓存条目。 CacheItemInterface 负责管理缓存条目: 读取缓存值 (get()) 判断缓存是否命中 (isHit()) 设置缓存值 (set()) 设置过期时间 (expiresAt(), expiresAfter()) - 总结
1. CacheItemPoolInterface 是缓存“池”接口,负责获取、保存、删除缓存项。 2. 每个缓存项通过 CacheItemInterface 表示,封装了具体数据和值和元信息(如过期时间、是否命中)。 3. 它是 PSR-6 规范的一部分,保证缓存库接口的统一。 4. Symfony 实现了这个接口,适配 Redis、Memcached、Filesystem 等多种缓存存储。 5. 使用这个接口,可以优雅且标准地操作缓存,避免直接操作 Redis 客户端细节。
对于Symfony 7 里你想用 Redis 缓存,一般就是用
Adapter\RedisAdapter,然后在配置文件里配置就可以了。1. Symfony 缓存适配器概念
Symfony\Component\Cache\Adapter\RedisAdapter是 Symfony Cache 组件提供的 Redis 缓存适配器。- 它实现了 PSR-6 的
CacheItemPoolInterface,你可以用它操作缓存(读写缓存项)。
2. 如何配置和使用 RedisAdapter
方法一:在 Symfony 配置文件中配置缓存
- 如果是 Symfony Flex 项目,一般在
config/packages/cache.yaml或config/packages/framework.yaml配置:
framework: cache: pools: app.redis_cache: adapter: 'cache.adapter.redis' default_lifetime: 3600 provider: 'redis://localhost' # 或者用环境变量- 这样配置后,你就可以在代码里通过依赖注入拿到这个缓存池:
use Psr\Cache\CacheItemPoolInterface; public function __construct(CacheItemPoolInterface $redisCache) { $this->cache = $redisCache; }- 或者你直接通过服务名获取:
app.redis_cache
方法二:手动创建 RedisAdapter
如果你想手动创建:
use Symfony\Component\Cache\Adapter\RedisAdapter; $redisClient = RedisAdapter::createConnection('redis://localhost'); $cache = new RedisAdapter($redisClient, $namespace = '', $defaultLifetime = 3600);然后
$cache就是一个符合 PSR-6 的缓存池。3. 常见环境变量配置
一般会把 Redis 连接串放到
.env文件:REDIS_URL=redis://localhost:6379然后在
framework.yaml里引用:framework: cache: pools: app.redis_cache: adapter: 'cache.adapter.redis' provider: '%env(REDIS_URL)%'4. 使用示例
$item = $cache->getItem('some_key'); if (!$item->isHit()) { $data = 'some expensive data'; $item->set($data); $cache->save($item); } else { $data = $item->get(); }总结
- Symfony 7 的缓存组件自带多种适配器(Redis、Filesystem、Memcached 等)。
- 你只要在配置文件中声明
adapter: cache.adapter.redis和 Redis 连接字符串即可。 - 也可以直接用
RedisAdapter手动创建缓存池对象。 - 通过依赖注入使用缓存,方便优雅。
关于PSR6
- 参考链接 https://www.php-fig.org/psr/psr-6/
CacheItemPoolInterface 来自 PSR-6(PHP Standards Recommendation 6),是 PHP-FIG(PHP Framework Interop Group)定义的缓存接口标准。
不是 PHP 自带:
PHP 本身(内核或标准库)没有缓存相关接口,这需要第三方库或者框架实现。
Symfony 的实现:
Symfony 7 及其缓存组件(symfony/cache 包)实现了 PSR-6 规范,并提供了具体的类(例如 Symfony\Component\Cache\Adapter\RedisAdapter)实现了这个接口。
安装方式:
需要通过 Composer 安装相关包(通常 symfony/cache 会自动依赖 psr/cache,其中包含接口定义)。也可以单独安装 composer require psr/cache
- symfony7包依赖关系
1. Symfony 7 框架 本身包含很多组件,但缓存相关功能主要由 symfony/cache 组件提供。
2. symfony/cache 组件实现了 PSR-6 和 PSR-16 缓存标准接口,支持多种缓存适配器(Redis、Memcached、Filesystem 等)。
3. PSR-6 规范接口 是由 psr/cache 这个包定义的,里面包含了 CacheItemPoolInterface、CacheItemInterface 等接口声明。
关于 PHP-FIG
PHP-FIG(PHP Framework Interop Group)是一个第三方组织,专门致力于推动 PHP 社区各大框架和库之间的互操作性和标准化。
- 全称:PHP Framework Interop Group
- 性质:开源社区组织(非盈利性质)
- 成立目的: 为了让不同 PHP 框架和库能更好地协同工作,制定一套统一的编码规范和接口标准(PSR,PHP Standards Recommendations)。
- 成员:来自多个主流 PHP 框架和库的开发者(比如 Symfony、Laravel、Zend Framework、Drupal 等)
- 工作方式:通过讨论和提案,发布规范(PSR),推动 PHP 生态标准化。
主要贡献
制定了很多重要的 PHP 标准规范,如:
- PSR-1:基础编码规范
- PSR-4:自动加载规范
- PSR-6:缓存接口规范
- PSR-7:HTTP 消息接口
- PSR-12:代码风格规范 等等...
影响
- PHP-FIG 的标准被绝大多数现代 PHP 框架和库广泛采纳。
- 它极大地促进了 PHP 生态系统的规范化和互通性。
- Composer(PHP 包管理工具)也很大程度上依赖这些标准。
简单总结
| 组织名 | 作用 | 特点 |
|---|---|---|
| PHP-FIG | 制定 PHP 标准规范(PSR 系列) | 社区驱动,跨框架协作组织 |
