Redis 快取介面卡
另請參閱
本文說明如何在任何 PHP 應用程式中,將快取作為獨立組件使用時,設定 Redis 介面卡。如果您在 Symfony 應用程式中使用快取,請閱讀Symfony 快取設定文章。
此介面卡使用一個(或多個)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 client 類別實例
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/主機(和選用埠)或 socket 路徑,以及密碼和資料庫索引。若要為連線啟用 TLS,scheme 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'
);
使用 PHP Redis Extension v5.2+ 或 Predis 程式庫時,也支援Redis Sentinel,它為 Redis 提供高可用性。使用 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
。如果您在擷取主要資訊時遇到問題,請將此明確設定為\Predis\Client
以用於 Sentinel。 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 的主節點名稱。
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 context 選項。請參閱 php.net/context.ssl 以取得更多資訊。
7.1
Symfony 7.1 中引入了作為 `redis_sentinel` 選項別名的 `sentinel_master` 選項。
注意
當使用 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 快取文件中閱讀有關此主題的更多資訊。
使用序列化器
用於基於標籤快取的 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);
使用 igbinary 序列化的 DefaultMarshaller
在可用時使用 ``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);