Redis 缓存适配器
另请参阅
本文介绍当在任何 PHP 应用程序中将 Cache 作为独立组件使用时,如何配置 Redis 适配器。如果您在 Symfony 应用程序中使用它,请阅读 Symfony Cache 配置 文章。
此适配器使用一个(或多个)Redis 服务器实例将值存储在内存中。
与 APCu 适配器 不同,但与 Memcached 适配器 类似,它不限于当前服务器的共享内存;您可以独立于 PHP 环境存储内容。还可以利用服务器集群来提供冗余和/或故障转移。
警告
要求:要使用此适配器,必须安装并运行至少一个 Redis 服务器。此外,此适配器需要一个兼容的扩展或库,该扩展或库实现了 \Redis
、\RedisArray
、RedisCluster
、\Relay\Relay
或 \Predis
。
此适配器期望将 Redis、RedisArray、RedisCluster、Relay 或 Predis 实例作为第一个参数传递。命名空间和默认缓存生命周期可以选择作为第二个和第三个参数传递
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
use Symfony\Component\Cache\Adapter\RedisAdapter;
$cache = new RedisAdapter(
// the object that stores a valid connection to your Redis system
\Redis $redisConnection,
// the string prefixed to the keys of the items stored in this cache
$namespace = '',
// the default lifetime (in seconds) for cache items that do not define their
// own lifetime, with a value 0 causing items to be stored indefinitely (i.e.
// until RedisAdapter::clear() is invoked or the server(s) are purged)
$defaultLifetime = 0,
// $marshaller (optional) An instance of MarshallerInterface to control the serialization
// and deserialization of cache items. By default, native PHP serialization is used.
// This can be useful for compressing data, applying custom serialization logic, or
// optimizing the size and performance of cached items
?MarshallerInterface $marshaller = null
);
配置连接
createConnection() 辅助方法允许使用 数据源名称 (DSN) 创建和配置 Redis 客户端类实例
1 2 3 4 5 6
use Symfony\Component\Cache\Adapter\RedisAdapter;
// pass a single DSN string to register a single server with the client
$client = RedisAdapter::createConnection(
'redis://127.0.0.1'
);
DSN 可以指定 IP/主机(和可选端口)或套接字路径,以及密码和数据库索引。要为连接启用 TLS,必须将方案 redis
替换为 rediss
(第二个 s
表示“安全”)。
注意
此适配器的 数据源名称 (DSN) 必须使用以下格式之一。
1
redis[s]://[pass@][ip|host|socket[:port]][/db-index]
1
redis[s]:[[user]:pass@]?[ip|host|socket[:port]][¶ms]
占位符 [user]
、[:port]
、[/db-index]
和 [¶ms]
的值是可选的。
以下是有效 DSN 的常见示例,显示了可用值的组合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
use Symfony\Component\Cache\Adapter\RedisAdapter;
// host "my.server.com" and port "6379"
RedisAdapter::createConnection('redis://my.server.com:6379');
// host "my.server.com" and port "6379" and database index "20"
RedisAdapter::createConnection('redis://my.server.com:6379/20');
// host "localhost", auth "abcdef" and timeout 5 seconds
RedisAdapter::createConnection('redis://abcdef@localhost?timeout=5');
// socket "/var/run/redis.sock" and auth "bad-pass"
RedisAdapter::createConnection('redis://bad-pass@/var/run/redis.sock');
// host "redis1" (docker container) with alternate DSN syntax and selecting database index "3"
RedisAdapter::createConnection('redis:?host[redis1:6379]&dbindex=3');
// providing credentials with alternate DSN syntax
RedisAdapter::createConnection('redis:default:verysecurepassword@?host[redis1:6379]&dbindex=3');
// a single DSN can also define multiple servers
RedisAdapter::createConnection(
'redis:?host[localhost]&host[localhost:6379]&host[/var/run/redis.sock:]&auth=my-password&redis_cluster=1'
);
Redis Sentinel 为 Redis 提供高可用性,在使用 PHP Redis Extension v5.2+ 或 Predis 库时也受支持。使用 redis_sentinel
参数设置您的服务组的名称
1 2 3 4 5 6 7 8 9 10 11 12 13
RedisAdapter::createConnection(
'redis:?host[redis1:26379]&host[redis2:26379]&host[redis3:26379]&redis_sentinel=mymaster'
);
// providing credentials
RedisAdapter::createConnection(
'redis:default:verysecurepassword@?host[redis1:26379]&host[redis2:26379]&host[redis3:26379]&redis_sentinel=mymaster'
);
// providing credentials and selecting database index "3"
RedisAdapter::createConnection(
'redis:default:verysecurepassword@?host[redis1:26379]&host[redis2:26379]&host[redis3:26379]&redis_sentinel=mymaster&dbindex=3'
);
注意
请参阅 RedisTrait 以获取更多可以作为 DSN 参数传递的选项。
配置选项
createConnection() 辅助方法还接受一个选项数组作为其第二个参数。期望的格式是表示选项名称及其各自值的 key => value
对的关联数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
use Symfony\Component\Cache\Adapter\RedisAdapter;
$client = RedisAdapter::createConnection(
// provide a string dsn
'redis://127.0.0.1:6379',
// associative array of configuration options
[
'class' => null,
'persistent' => 0,
'persistent_id' => null,
'timeout' => 30,
'read_timeout' => 0,
'retry_interval' => 0,
'tcp_keepalive' => 0,
'lazy' => null,
'redis_cluster' => false,
'redis_sentinel' => null,
'dbindex' => 0,
'failover' => 'none',
'ssl' => null,
]
);
可用选项
class
(类型:string
, 默认值:null
)- 指定要返回的连接库,可以是
\Redis
、\Relay\Relay
或\Predis\Client
。 如果未指定,则回退值按以下顺序排列,具体取决于哪个先可用:\Redis
、\Relay\Relay
、\Predis\Client
。 如果您在检索主信息时遇到问题,请显式地将其设置为 Sentinel 的\Predis\Client
。 persistent
(类型:int
, 默认值:0
)- 启用或禁用持久连接的使用。 值
0
禁用持久连接,值1
启用它们。 persistent_id
(类型:string|null
, 默认值:null
)- 指定用于持久连接的持久 ID 字符串。
timeout
(类型:int
, 默认值:30
)- 指定连接到 Redis 服务器之前连接尝试超时的时长(以秒为单位)。
read_timeout
(类型:int
, 默认值:0
)- 指定在底层网络资源上执行读取操作之前操作超时的时长(以秒为单位)。
retry_interval
(类型:int
, 默认值:0
)- 指定客户端与服务器断开连接时,重新连接尝试之间的延迟(以毫秒为单位)。
tcp_keepalive
(类型:int
, 默认值:0
)- 指定连接的 TCP-keepalive 超时时间(以秒为单位)。 这需要 phpredis v4 或更高版本以及启用 TCP-keepalive 的服务器。
lazy
(类型:bool
, 默认值:null
)- 启用或禁用与后端的延迟连接。 当将其用作独立组件时,默认为
false
;当在 Symfony 应用程序内部使用时,默认为true
。 redis_cluster
(类型:bool
, 默认值:false
)- 启用或禁用 redis 集群。 传递的实际值无关紧要,只要它通过宽松的比较检查即可:
redis_cluster=1
就足够了。 redis_sentinel
(类型:string
, 默认值:null
)- 指定连接到哨兵的主服务器名称。
sentinel_master
(类型:string
, 默认值:null
)redis_sentinel
选项的别名。dbindex
(类型:int
, 默认值:0
)- 指定要选择的数据库索引。
failover
(类型:string
, 默认值:none
)- 指定集群实现的故障转移。 对于
\RedisCluster
,有效选项为none
(默认)、error
、distribute
或slaves
。 对于\Predis\ClientInterface
,有效选项为slaves
或distribute
。 ssl
(类型:array
, 默认值:null
)- SSL 上下文选项。 有关更多信息,请参阅 php.net/context.ssl。
7.1
作为 redis_sentinel
别名的 `sentinel_master` 选项在 Symfony 7.1 中引入。
注意
当使用 Predis 库时,可以使用一些额外的 Predis 特有选项。 有关更多信息,请参考 Predis 连接参数文档。
配置 Redis
当使用 Redis 作为缓存时,您应该配置 maxmemory
和 maxmemory-policy
设置。 通过设置 maxmemory
,您可以限制 Redis 可以消耗的内存量。 如果数量太少,Redis 将删除仍然有用的条目,并且您从缓存中获得的收益会减少。 将 maxmemory-policy
设置为 allkeys-lru
会告诉 Redis,当内存耗尽时可以删除数据,并首先删除最旧的条目(最近最少使用的)。 如果您不允许 Redis 删除条目,则当您尝试在没有可用内存时添加数据时,它将返回错误。 示例设置可能如下所示
1 2
maxmemory 100mb
maxmemory-policy allkeys-lru
使用标签
为了使用基于标签的失效,您可以将适配器包装在 TagAwareAdapter 中。 但是,当 Redis 用作后端时,使用专用的 RedisTagAwareAdapter 通常更有趣。 由于标签失效逻辑在 Redis 本身中实现,因此当使用基于标签的失效时,此适配器可提供更好的性能
1 2 3 4 5
use Symfony\Component\Cache\Adapter\RedisAdapter;
use Symfony\Component\Cache\Adapter\RedisTagAwareAdapter;
$client = RedisAdapter::createConnection('redis://127.0.0.1');
$cache = new RedisTagAwareAdapter($client);
注意
当使用 RedisTagAwareAdapter 时,为了维护标签和缓存项之间的关系,您必须在 Redis maxmemory-policy
驱逐策略中使用 noeviction
或 volatile-*
。
在官方 Redis LRU 缓存文档中阅读有关此主题的更多信息。
使用 Marshaller
TagAwareMarshaller 用于基于标签的缓存
优化基于标签检索的缓存,从而可以有效地管理相关项
1 2 3 4 5 6 7
$marshaller = new TagAwareMarshaller();
$cache = new RedisAdapter($redis, 'tagged_namespace', 3600, $marshaller);
$item = $cache->getItem('tagged_key');
$item->set(['value' => 'some_data', 'tags' => ['tag1', 'tag2']]);
$cache->save($item);
SodiumMarshaller 用于加密缓存
使用 Sodium 加密缓存数据,以增强安全性
1 2 3 4 5 6 7 8
$encryptionKeys = [sodium_crypto_box_keypair()];
$marshaller = new SodiumMarshaller($encryptionKeys);
$cache = new RedisAdapter($redis, 'secure_namespace', 3600, $marshaller);
$item = $cache->getItem('secure_key');
$item->set('confidential_data');
$cache->save($item);
DefaultMarshaller 使用 igbinary 序列化
当可用时,使用 ``igbinary` 进行更快更高效的序列化
1 2 3 4 5 6 7
$marshaller = new DefaultMarshaller(true);
$cache = new RedisAdapter($redis, 'optimized_namespace', 3600, $marshaller);
$item = $cache->getItem('optimized_key');
$item->set(['data' => 'optimized_data']);
$cache->save($item);
DefaultMarshaller 在失败时抛出异常
如果序列化失败,则抛出异常,方便错误处理
1 2 3 4 5 6 7 8 9 10 11
$marshaller = new DefaultMarshaller(false, true);
$cache = new RedisAdapter($redis, 'error_namespace', 3600, $marshaller);
try {
$item = $cache->getItem('error_key');
$item->set('data');
$cache->save($item);
} catch (\ValueError $e) {
echo 'Serialization failed: '.$e->getMessage();
}
SodiumMarshaller 支持密钥轮换
支持密钥轮换,确保使用新旧密钥进行安全解密
1 2 3 4 5 6 7 8
$keys = [sodium_crypto_box_keypair(), sodium_crypto_box_keypair()];
$marshaller = new SodiumMarshaller($keys);
$cache = new RedisAdapter($redis, 'rotated_namespace', 3600, $marshaller);
$item = $cache->getItem('rotated_key');
$item->set('data_to_encrypt');
$cache->save($item);