適用於 PHP 7.2 及更高版本的靈活且功能齊全的 Redis 用戶端。
有關該項目的更多詳細資訊可以在常見問題中找到。
EVALSHA
或EVAL
之間的自動切換。SCAN
、 SSCAN
、 ZSCAN
和HSCAN
(Redis >= 2.8) 的抽象化。該程式庫可以在 Packagist 上找到,以便使用 Composer 更輕鬆地管理專案依賴項。每個版本的壓縮檔案均可在 GitHub 上找到。
composer require predis/predis
Predis 依靠 PHP 的自動載入功能在需要時載入其文件,並符合 PSR-4 標準。當透過 Composer 管理依賴項時,自動載入會自動處理,但也可以在缺乏任何自動載入功能的項目或腳本中利用自己的自動載入器:
// Prepend a base path if Predis is not available in your "include_path".
require ' Predis/Autoloader.php ' ;
Predis Autoloader:: register ();
當建立客戶端實例而不傳遞任何連線參數時,Predis 假定127.0.0.1
和6379
作為預設主機和連接埠。 connect()
操作的預設逾時為 5 秒:
$ client = new Predis Client ();
$ client -> set ( ' foo ' , ' bar ' );
$ value = $ client -> get ( ' foo ' );
連接參數可以以 URI 字串或命名數組的形式提供。後者是提供參數的首選方式,但是當從非結構化或部分結構化來源讀取參數時,URI 字串可能很有用:
// Parameters passed using a named array:
$ client = new Predis Client ([
' scheme ' => ' tcp ' ,
' host ' => ' 10.0.0.1 ' ,
' port ' => 6379 ,
]);
// Same set of parameters, passed using an URI string:
$ client = new Predis Client ( ' tcp://10.0.0.1:6379 ' );
可以透過在參數集中添加password
來存取受密碼保護的伺服器。當 Redis >= 6.0 上啟用 ACL 時,使用者驗證需要username
和password
。
也可以使用 UNIX 域套接字連接到 Redis 的本機實例,在這種情況下,參數必須使用unix
方案並指定套接字檔案的路徑:
$ client = new Predis Client ([ ' scheme ' => ' unix ' , ' path ' => ' /path/to/redis.sock ' ]);
$ client = new Predis Client ( ' unix:/path/to/redis.sock ' );
用戶端可以利用 TLS/SSL 加密連線到安全的遠端 Redis 實例,而無需配置 stunnel 等 SSL 代理程式。當連接到在各種雲端託管提供者上運行的節點時,這非常有用。可以使用tls
方案和透過ssl
參數傳遞的一系列合適選項來啟用加密:
// Named array of connection parameters:
$ client = new Predis Client ([
' scheme ' => ' tls ' ,
' ssl ' => [ ' cafile ' => ' private.pem ' , ' verify_peer ' => true ],
]);
// Same set of parameters, but using an URI string:
$ client = new Predis Client ( ' tls://127.0.0.1?ssl[cafile]=private.pem&ssl[verify_peer]=1 ' );
也支援連接方案redis
( tcp
的別名)和rediss
( tls
的別名),不同之處在於包含這些方案的 URI 字串是按照其各自的 IANA 臨時註冊文件中所述的規則進行解析的。
支援的連接參數的實際清單可能因每個連接後端而異,因此建議參考其特定文件或實作以了解詳細資訊。
Predis 可以在提供一系列連接參數和適當的選項來指示客戶端如何聚合它們(叢集、複製或自訂聚合邏輯)時聚合多個連線。為每個節點提供配置時,可以混合命名數組和 URI 字串:
$ client = new Predis Client ([
' tcp://10.0.0.1?alias=first-node ' , [ ' host ' => ' 10.0.0.2 ' , ' alias ' => ' second-node ' ],
], [
' cluster ' => ' predis ' ,
]);
有關更多詳細信息,請參閱本文檔的聚合連接部分。
與 Redis 的連接是惰性的,這意味著客戶端僅在需要時才連接到伺服器。雖然建議讓客戶端在背景做自己的事情,但有時可能仍需要控制連線的開啟或關閉時間:這可以透過呼叫$client->connect()
和$client->disconnect()
。請注意,這些方法對聚合連接的影響可能會有所不同,具體取決於每個特定的實作。
可以透過將特定的客戶端選項傳遞給PredisClient::__construct()
的第二個參數來配置客戶端的許多面向和行為:
$ client = new Predis Client ( $ parameters , [ ' prefix ' => ' sample: ' ]);
選項使用迷你 DI 類似容器進行管理,並且它們的值可以僅在需要時才進行延遲初始化。 Predis 預設支援的客戶端選項有:
prefix
:應用於命令中找到的每個鍵的前綴字串。exceptions
:客戶端是否應該在 Redis 錯誤時拋出或回傳回應。connections
:連接後端或連接工廠實例的清單。cluster
:指定叢集後端( predis
、 redis
或 callable )。replication
:指定複製後端( predis
、 sentinel
或 callable)。aggregate
:使用自訂聚合連線(可呼叫)來設定客戶端。parameters
:聚合連線的預設連線參數清單。commands
:指定要透過庫使用的命令工廠實例。使用者還可以提供帶有值或可調用物件(用於延遲初始化)的自訂選項,這些值或可調用物件儲存在選項容器中,以便以後透過庫使用。
聚合連接是 Predis 實現叢集和複製的基礎,它們用於將多個連接分組到單個 Redis 節點,並隱藏根據上下文正確處理它們所需的特定邏輯。在建立新客戶端實例時,聚合連線通常需要一組連線參數以及適當的客戶端選項。
Predis 可以配置為使用傳統客戶端分片方法在叢集模式下運作,以建立獨立節點的叢集並在它們之間指派金鑰空間。這種方法需要對節點進行某種外部運行狀況監控,並且需要在新增或刪除節點時手動重新平衡鍵空間:
$ parameters = [ ' tcp://10.0.0.1 ' , ' tcp://10.0.0.2 ' , ' tcp://10.0.0.3 ' ];
$ options = [ ' cluster ' => ' predis ' ];
$ client = new Predis Client ( $ parameters );
與 Redis 3.0 一起,引入了一種新的有監督和協調的集群類型,即 redis-cluster。這種方法使用不同的演算法來分配金鑰空間,Redis 節點透過八卦協定進行通訊來協調自身,以處理健康狀態、重新平衡、節點發現和請求重定向。為了連接到由 redis-cluster 管理的集群,客戶端需要一個其節點列表(不一定完整,因為它會在必要時自動發現新節點)並將cluster
客戶端選項設為redis
:
$ parameters = [ ' tcp://10.0.0.1 ' , ' tcp://10.0.0.2 ' , ' tcp://10.0.0.3 ' ];
$ options = [ ' cluster ' => ' redis ' ];
$ client = new Predis Client ( $ parameters , $ options );
客戶端可以配置為在單主/多從設定中運行,以提供更好的服務可用性。使用複製時,Predis 會識別只讀命令並將它們發送到隨機從屬伺服器,以便提供某種負載平衡,並在檢測到執行任何最終會修改的操作的命令時立即切換到主伺服器鍵空間或鍵的值。當從屬設備發生故障時,客戶端不會嘗試回退到配置中提供的其他從屬設備,而不是引發連線錯誤。
在複製模式下使用客戶端所需的基本配置需要將一台 Redis 伺服器識別為主伺服器(這可以透過連線參數將role
參數設為master
來完成)和一個或多個從伺服器(在本例中將role
設定為從slave
對於奴隸是可選的):
$ parameters = [ ' tcp://10.0.0.1?role=master ' , ' tcp://10.0.0.2 ' , ' tcp://10.0.0.3 ' ];
$ options = [ ' replication ' => ' predis ' ];
$ client = new Predis Client ( $ parameters , $ options );
上面的配置有一個靜態的伺服器列表,完全依賴客戶端的邏輯,但是可以依靠redis-sentinel
來獲得更強大的 HA 環境,其中 Sentinel 伺服器充當客戶端進行服務發現的授權來源。客戶端使用 redis-sentinel 所需的最低配置是指向一堆哨兵實例的連接參數列表, replication
選項設定為sentinel
, service
選項設定為服務名稱:
$ sentinels = [ ' tcp://10.0.0.1 ' , ' tcp://10.0.0.2 ' , ' tcp://10.0.0.3 ' ];
$ options = [ ' replication ' => ' sentinel ' , ' service ' => ' mymaster ' ];
$ client = new Predis Client ( $ sentinels , $ options );
如果主節點和從節點配置為要求客戶端進行身份驗證,則必須透過全域parameters
用戶端選項提供密碼。此選項也可用於指定不同的資料庫索引。客戶端選項數組將如下所示:
$ options = [
' replication ' => ' sentinel ' ,
' service ' => ' mymaster ' ,
' parameters ' => [
' password ' => $ secretpassword ,
' database ' => 10 ,
],
];
雖然 Predis 能夠區分執行寫入和只讀操作的命令,但EVAL
和EVALSHA
代表了一種極端情況,即客戶端切換到主節點,因為它無法判斷 Lua 腳本何時可以在從屬節點上安全地執行。雖然這確實是預設行為,但當某些 Lua 腳本不執行寫入操作時,可以提供提示來告訴客戶端堅持使用從屬程式來執行:
$ parameters = [ ' tcp://10.0.0.1?role=master ' , ' tcp://10.0.0.2 ' , ' tcp://10.0.0.3 ' ];
$ options = [ ' replication ' => function () {
// Set scripts that won't trigger a switch from a slave to the master node.
$ strategy = new Predis Replication ReplicationStrategy ();
$ strategy -> setScriptReadOnly ( $ LUA_SCRIPT );
return new Predis Connection Replication MasterSlaveReplication ( $ strategy );
}];
$ client = new Predis Client ( $ parameters , $ options );
$ client -> eval ( $ LUA_SCRIPT , 0 ); // Sticks to slave using `eval`...
$ client -> evalsha ( sha1 ( $ LUA_SCRIPT ), 0 ); // ... and `evalsha`, too.
examples
目錄包含一些腳本,這些腳本示範如何在基本和複雜場景中配置和使用客戶端來利用複製。
當需要將許多命令傳送到伺服器時,管道化可以透過減少網路往返時間帶來的延遲來提高效能。管道也適用於聚合連接。由於其流暢的接口,客戶端可以在可調用區塊內執行管道或返回具有連結命令能力的管道實例:
// Executes a pipeline inside the given callable block:
$ responses = $ client -> pipeline ( function ( $ pipe ) {
for ( $ i = 0 ; $ i < 1000 ; $ i ++) {
$ pipe -> set ( " key: $ i " , str_pad ( $ i , 4 , ' 0 ' , 0 ));
$ pipe -> get ( " key: $ i " );
}
});
// Returns a pipeline that can be chained thanks to its fluent interface:
$ responses = $ client -> pipeline ()-> set ( ' foo ' , ' bar ' )-> get ( ' foo ' )-> execute ();
用戶端為基於MULTI
和EXEC
Redis 交易提供抽象,並具有與命令管道類似的介面:
// Executes a transaction inside the given callable block:
$ responses = $ client -> transaction ( function ( $ tx ) {
$ tx -> set ( ' foo ' , ' bar ' );
$ tx -> get ( ' foo ' );
});
// Returns a transaction that can be chained thanks to its fluent interface:
$ responses = $ client -> transaction ()-> set ( ' foo ' , ' bar ' )-> get ( ' foo ' )-> execute ();
由於WATCH
和UNWATCH
這種抽象可以執行檢查和設定操作,並在觸碰WATCH
ed 鍵時自動重試 Redis 中止的交易。有關使用 CAS 的事務範例,您可以查看以下範例。
雖然我們嘗試更新 Predis 以了解 Redis 中可用的所有命令,但您可能更願意堅持使用舊版本的庫,或者提供不同的方法來過濾參數或解析特定命令的回應。為了實現這一點,Predis 提供了實作新命令類別的能力,以定義或覆寫客戶端使用的預設命令工廠中的命令:
// Define a new command by extending PredisCommandCommand:
class BrandNewRedisCommand extends Predis Command Command
{
public function getId ()
{
return ' NEWCMD ' ;
}
}
// Inject your command in the current command factory:
$ client = new Predis Client ( $ parameters , [
' commands ' => [
' newcmd ' => ' BrandNewRedisCommand ' ,
],
]);
$ response = $ client -> newcmd ();
還有一種方法可以發送原始命令而不過濾其參數或解析回應。使用者必須以數組形式提供命令的參數列表,遵循 Redis 文件中命令定義的簽名:
$ response = $ client -> executeRaw ([ ' SET ' , ' foo ' , ' bar ' ]);
雖然可以直接使用EVAL
和EVALSHA
在 Redis 2.6+ 上利用 Lua 腳本,但 Predis 提供腳本命令作為構建在它們之上的更高級別的抽象,以使事情變得簡單。腳本命令可以在客戶端使用的命令工廠中註冊,並且可以像普通 Redis 命令一樣進行訪問,但它們定義了傳輸到伺服器以進行遠端執行的 Lua 腳本。在內部,他們預設使用EVALSHA
並透過 SHA1 雜湊來識別腳本以節省頻寬,但EVAL
在需要時用作後備:
// Define a new script command by extending PredisCommandScriptCommand:
class ListPushRandomValue extends Predis Command ScriptCommand
{
public function getKeysCount ()
{
return 1 ;
}
public function getScript ()
{
return <<<LUA
math.randomseed(ARGV[1])
local rnd = tostring(math.random())
redis.call('lpush', KEYS[1], rnd)
return rnd
LUA ;
}
}
// Inject the script command in the current command factory:
$ client = new Predis Client ( $ parameters , [
' commands ' => [
' lpushrand ' => ' ListPushRandomValue ' ,
],
]);
$ response = $ client -> lpushrand ( ' random_values ' , $ seed = mt_rand ());
Predis 可以使用不同的連接後端來連接到 Redis。內建的 Relay 整合透過在 PHP 共享運行時記憶體中快取 Redis 資料集的部分副本,利用 PHP 的 Relay 擴充功能來顯著提高效能。
$ client = new Predis Client ( ' tcp://127.0.0.1 ' , [
' connections ' => ' relay ' ,
]);
開發人員可以創建自己的連接類別來支援全新的網路後端、擴展現有類別或提供完全不同的實作。連線類別必須實作PredisConnectionNodeConnectionInterface
或擴充PredisConnectionAbstractConnection
:
class MyConnectionClass implements Predis Connection NodeConnectionInterface
{
// Implementation goes here...
}
// Use MyConnectionClass to handle connections for the `tcp` scheme:
$ client = new Predis Client ( ' tcp://127.0.0.1 ' , [
' connections ' => [ ' tcp ' => ' MyConnectionClass ' ],
]);
若要更深入地了解如何建立新的連線後端,您可以參考PredisConnection
命名空間中可用的標準連線類別的實際實作。
對 Predis 的貢獻受到高度讚賞,無論是以新功能拉取請求、錯誤修復還是錯誤報告的形式。我們只要求您遵守問題和拉取請求範本。
注意:切勿針對在生產環境中執行或包含您感興趣的資料的 Redis 執行個體執行 Predis 隨附的測試套件!
Predis 有一個全面的測試套件,涵蓋了庫的各個方面,並且可以選擇針對正在運行的 Redis 實例執行集成測試(需要 >= 2.4.0,以便驗證每個命令實現的正確行為。不支援的集成測試如果您沒有啟動並執行Redis,則可以停用Redis 命令,有關測試此程式庫的更多詳細信息,請參閱測試自述文件。
Predis 使用 GitHub Actions 進行持續集成,過去和目前建置的歷史記錄可以在其操作頁面上找到。
Predis 的程式碼是根據 MIT 授權的條款分發的(請參閱許可證)。