多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# 自述文件 [![软件许可证](https://camo.githubusercontent.com/ff381ed65f0c68b3ee1bf447a1f79ac5c4552fe286596bce5aaecf57168416e8/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f7072656469732f7072656469732e7376673f7374796c653d666c61742d737175617265)](https://github.com/predis/predis/blob/HEAD/LICENSE)[![最新稳定](https://camo.githubusercontent.com/5a9158c93412ea50e44132c3a78f4b62d72404a70f23d54d7cb4af79060acfff/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7072656469732f7072656469732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/predis/predis)[![最新发展](https://camo.githubusercontent.com/ce6a5ee6fc80716b60bc0fcdc7dde4edbda75695f1d186b7234a81ac75b7f9bd/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f767072652f7072656469732f7072656469732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/predis/predis)[![每月安装](https://camo.githubusercontent.com/4c6c1edbae6b049cbe20573723e0e8c45148e0ea0b1c2d0f7c6bb7c0f58c5681/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646d2f7072656469732f7072656469732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/predis/predis/stats)[![构建状态](https://camo.githubusercontent.com/e373d2c427bce14b0f90434e1bef9c1991876d4a90f5d18b1e49e28701b8f057/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f7072656469732f7072656469732f54657374732f6d61696e3f7374796c653d666c61742d737175617265)](https://github.com/predis/predis/actions) 适用于 PHP 7.2 及更高版本的灵活且功能完整的[Redis客户端。](http://redis.io/) **注意:**您位于 Predis 不稳定分支的 README 文件中,专门用于开发未来版本。这意味着此分支上的代码可能不稳定,并且可能会在没有任何事先通知的情况下发生重大更改。不要在生产环境中使用它或使用它需要您自担风险! Predis 默认不需要任何额外的 C 扩展,但可以选择与[ppiredis](https://github.com/nrk/phpiredis)配对,以降低[Redis RESP 协议](http://redis.io/topics/protocol)的序列化和解析开销。 关于这个项目的更多细节可以在[常见问题](https://github.com/predis/predis/blob/HEAD/FAQ.md)中找到。 ## [](http://packagist.p2hp.com/packages/predis/predis#user-content-main-features)主要特点 * 支持从**2.0**到**6.0**的 Redis 。 * 支持使用客户端分片和可插入键空间分发器进行集群。 * 支持[redis-cluster](http://redis.io/topics/cluster-tutorial)(Redis >= 3.0)。 * 支持主从复制设置和[redis-sentinel](http://redis.io/topics/sentinel)。 * 使用可自定义的前缀策略对键进行透明的键前缀。 * 单个节点和集群上的命令流水线(仅限客户端分片)。 * Redis 事务 (Redis >= 2.0) 和 CAS 操作 (Redis >= 2.2) 的抽象。 * `EVALSHA`Lua 脚本的抽象(Redis >= 2.6)和在or之间自动切换`EVAL`。 * 基于 PHP 迭代器的 、 和 (Redis >= 2.8`SCAN`)`SSCAN`的`ZSCAN`抽象。`HSCAN` * 连接是由客户端在第一个命令时延迟建立的,并且可以持久化。 * 可以通过 TCP/IP(也是 TLS/SSL 加密)或 UNIX 域套接字建立连接。 * 支持[Webdis](http://webd.is/)(同时需要`ext-curl`和`ext-phpiredis`)。 * 支持自定义连接类以提供不同的网络或协议后端。 * 用于定义自定义命令并覆盖默认命令的灵活系统。 ## [](http://packagist.p2hp.com/packages/predis/predis#user-content-how-to-install-and-use-predis)如何*安装*和使用 Predis 这个库可以在[Packagist](http://packagist.org/packages/predis/predis)上找到,以便使用[Composer](http://packagist.org/about-composer)更轻松地管理项目依赖项。[GitHub 上提供](https://github.com/predis/predis/releases)了每个版本的压缩档案。 ### [](http://packagist.p2hp.com/packages/predis/predis#user-content-loading-the-library)加载库 Predis 依靠 PHP 的自动加载功能在需要时加载其文件,并符合[PSR-4 标准](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md)。当通过 Composer 管理依赖项时,自动加载会自动处理,但也可以在缺少任何自动加载工具的项目或脚本中利用其自己的自动加载器: ~~~ // 如果 Predis 在您的“include_path”中不可用,则添加一个基本路径。 需要 'Predis/Autoloader.php'; Predis \ Autoloader :: register (); ~~~ ### [](http://packagist.p2hp.com/packages/predis/predis#user-content-connecting-to-redis)连接到 Redis 在不传递任何连接参数的情况下创建客户端实例时,Predis 假定`127.0.0.1`和`6379`作为默认主机和端口。操作的默认超时为`connect()`5 秒: ~~~ $ client = new Predis \ Client (); $客户端->设置( 'foo', 'bar'); $价值= $客户->获取( 'foo'); ~~~ 连接参数可以以 URI 字符串或命名数组的形式提供。后者是提供参数的首选方式,但当从非结构化或部分结构化的源中读取参数时,URI 字符串会很有用: ~~~ // 使用命名数组传递的参数: $ client = new Predis \ Client ([ 'scheme' => 'tcp' , 'host' => '10.0.0.1' , 'port' => 6379 , ]); // 相同的参数集,使用 URI 字符串传递: $ 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`的一组合适的[选项来启用加密:](http://php.net/manual/context.ssl.php)`ssl` ~~~ // 命名的连接参数数组: $ client = new Predis \ Client ([ 'scheme' => 'tls' , 'ssl' => [ 'cafile' => 'private.pem' , 'verify_peer' => true ] , ]); // 相同的参数集,但使用 URI 字符串: $ client = new Predis \ Client ( 'tls://127.0.0.1?ssl[cafile]=private.pem&ssl[verify_peer]=1' ); ~~~ 还支持连接方案[`redis`](http://www.iana.org/assignments/uri-schemes/prov/redis)(的别名`tcp`)和[`rediss`](http://www.iana.org/assignments/uri-schemes/prov/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' ], ],[ '集群' => 'predis' , ]); ~~~ 有关更多详细信息,请参阅本文档的[聚合连接](http://packagist.p2hp.com/packages/predis/predis#user-content-aggregate-connections)部分。 与 Redis 的连接是惰性的,这意味着客户端仅在需要时才连接到服务器。虽然建议让客户端在后台做自己的事情,但有时仍希望控制连接何时打开或关闭:这可以通过调用`$client->connect()`和轻松实现`$client->disconnect()`。请注意,这些方法对聚合连接的影响可能因每个具体实现而异。 ### [](http://packagist.p2hp.com/packages/predis/predis#user-content-client-configuration)客户端配置 可以通过将特定的客户端选项传递给 的第二个参数来配置客户端的许多方面和行为`Predis\Client::__construct()`: ~~~ $ client = new Predis \ Client ( $ parameters , [ 'prefix' => 'sample:' ]); ~~~ 选项使用类似 DI 的迷你容器进行管理,并且它们的值仅在需要时才可以延迟初始化。Predis 默认支持的客户端选项有: * `prefix`: 前缀字符串应用于命令中找到的每个键。 * `exceptions`:客户端是否应该在 Redis 错误时抛出或返回响应。 * `connections`:连接后端或连接工厂实例的列表。 * `cluster`: 指定集群后端(`predis`或`redis`可调用)。 * `replication`: 指定复制后端(`predis`或`sentinel`可调用)。 * `aggregate`:使用自定义聚合连接(可调用)配置客户端。 * `parameters`:聚合连接的默认连接参数列表。 * `commands`:指定要通过库使用的命令工厂实例。 用户还可以为自定义选项提供存储在选项容器中的值或可调用对象(用于延迟初始化),以供以后通过库使用。 ### [](http://packagist.p2hp.com/packages/predis/predis#user-content-aggregate-connections)聚合连接 聚合连接是 Predis 实现集群和复制的基础,它们用于将多个连接分组到单个 Redis 节点,并根据上下文隐藏正确处理它们所需的特定逻辑。在创建新的客户端实例时,聚合连接通常需要一系列连接参数以及适当的客户端选项。 #### [](http://packagist.p2hp.com/packages/predis/predis#user-content-cluster)簇 Predis 可以配置为使用传统的客户端分片方法以集群模式工作,以创建独立节点的集群并在它们之间分配密钥空间。这种方法需要对节点进行某种外部健康监控,并且需要在添加或删除节点时手动重新平衡键空间: ~~~ $参数= [ 'tcp://10.0.0.1' , 'tcp://10.0.0.2' , 'tcp://10.0.0.3' ]; $选项 = [ '集群' => 'predis' ]; $ client = new Predis \ Client ( $ parameters ); ~~~ 与 Redis 3.0 一起,以[redis-cluster](http://redis.io/topics/cluster-tutorial)的形式引入了一种新的有监督和协调的集群类型。这种方法使用不同的算法来分配密钥空间,Redis 节点通过 gossip 协议进行通信来协调自己,以处理健康状态、重新平衡、节点发现和请求重定向。为了连接到由 redis-cluster 管理的集群,客户端需要一个节点列表(不一定完整,因为它会在必要时自动发现新节点)并且`cluster`客户端选项设置为`redis`: ~~~ $参数= [ 'tcp://10.0.0.1' , 'tcp://10.0.0.2' , 'tcp://10.0.0.3' ]; $选项 = [ '集群' => 'redis' ]; $ client = new Predis \ Client ( $ parameters , $ options ); ~~~ #### [](http://packagist.p2hp.com/packages/predis/predis#user-content-replication)复制 客户端可以配置为在单个主/多个从设置中运行,以提供更好的服务可用性。使用复制时,Predis 识别只读命令并将它们发送到随机从属,以提供某种负载平衡,并在检测到执行任何最终会修改的操作的命令时切换到主控键空间或键的值。当从站失败时,客户端不会引发连接错误,而是尝试回退到配置中提供的从站中的不同从站。 在复制模式下使用客户端所需的基本配置需要将一台 Redis 服务器标识为主服务器(这可以通过将参数设置为 来通过连接参数完成`role`)`master`和一个或多个从服务器(在这种情况下,设置`role`为`slave`从属服务器是可选的): ~~~ $参数= [ 'tcp://10.0.0.1?role=master' , 'tcp://10.0.0.2' , 'tcp://10.0.0.3' ]; $选项 = [ '复制' => 'predis' ]; $ client = new Predis \ Client ( $ parameters , $ options ); ~~~ 上面的配置有一个静态的服务器列表,完全依赖于客户端的逻辑,但是可以依赖于[`redis-sentinel`](http://redis.io/topics/sentinel)一个更健壮的 HA 环境,其中哨兵​​服务器充当客户端进行服务发现的权限来源。客户端使用 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 脚本不执行写操作时,可以提供一个提示来告诉客户端坚持使用从属来执行它们: ~~~ $参数= [ 'tcp://10.0.0.1?role=master' , 'tcp://10.0.0.2' , 'tcp://10.0.0.3' ]; $ options = [ 'replication' => function () { // 设置不会触发从从节点切换到主节点的脚本。 $策略=新的 Predis \复制\复制策略(); $策略-> setScriptReadOnly ( $ LUA_SCRIPT ); 返回 新的 Predis \ Connection \ Replication \ MasterSlaveReplication($策略); }]; $ client = new Predis \ Client ( $ parameters , $ options ); $客户端->评估( $ LUA_SCRIPT, 0); // 使用 `eval` 连接到 slave... $ client -> evalsha ( sha1 ( $ LUA_SCRIPT ), 0 ); // ... 还有 `evalsha`。 ~~~ 该[`examples`](https://github.com/predis/predis/blob/HEAD/examples/)目录包含一些脚本,这些脚本演示了如何配置客户端并将其用于在基本和复杂场景中利用复制。 ### [](http://packagist.p2hp.com/packages/predis/predis#user-content-command-pipelines)命令管道 当需要将许多命令发送到服务器时,流水线可以通过减少网络往返时间引入的延迟来帮助提高性能。流水线也适用于聚合连接。由于其流畅的接口,客户端可以在可调用块内执行管道或返回具有链接命令能力的管道实例: ~~~ // 在给定的可调用块内执行管道: $ response = $ client -> pipeline ( function ( $ pipe ) { for ( $ i = 0 ; $ i < 1000 ; $ i ++) { $ pipe -> set ( "key:$i" , str_pad ( $ i , 4 , '0' , 0 )); $管道->获取( "key:$i" ); } }); // 由于其流畅的接口,返回一个可以链接的管道: $ responses = $ client -> pipeline ()-> set ( 'foo' , 'bar' )-> get ( 'foo' )-> execute () ; ~~~ ### [](http://packagist.p2hp.com/packages/predis/predis#user-content-transactions)交易 客户端为 Redis 事务提供了一个抽象,它基于命令管道`MULTI`并`EXEC`具有与命令管道类似的接口: ~~~ // 在给定的可调用块内执行事务: $ responses = $ client -> transaction ( function ( $ tx ) { $ tx -> set ( 'foo' , 'bar' ); $ tx -> get ( 'foo' ); }); // 由于其流畅的接口,返回一个可以链接的事务: $ response = $ client -> transaction ()-> set ( 'foo' , 'bar' )-> get ( 'foo' )-> execute () ; ~~~ 这种抽象可以执行检查和设置操作,`WATCH`并在ed 键被触摸`UNWATCH`时提供由 Redis 中止的事务的自动重试。`WATCH`对于使用 CAS 的事务示例,您可以查看[以下示例](https://github.com/predis/predis/blob/HEAD/examples/transaction_using_cas.php)。 ### [](http://packagist.p2hp.com/packages/predis/predis#user-content-adding-new-commands)添加新命令 虽然我们尝试更新 Predis 以与 Redis 中可用的所有命令保持同步,但您可能更愿意坚持使用旧版本的库或提供不同的方式来过滤参数或解析特定命令的响应。为了实现这一点,Predis 提供了实现新命令类的能力,以在客户端使用的默认命令工厂中定义或覆盖命令: ~~~ // 通过扩展 Predis\Command\Command 定义一个新命令: class BrandNewRedisCommand extends Predis \ Command \ Command { 公共 函数 getId () { 返回 'NEWCMD' ; } } // 在当前命令工厂中注入你的命令: $ client = new Predis \ Client ( $ parameters , [ 'commands' => [ 'newcmd' => 'BrandNewRedisCommand' , ], ]); $响应= $客户端-> newcmd (); ~~~ 还有一种方法可以在不过滤参数或解析响应的情况下发送原始命令。[用户必须按照Redis 文档中为 commands](http://redis.io/commands)定义的签名,将命令的参数列表作为数组提供: ~~~ $ response = $ client -> executeRaw ([ 'SET' , 'foo' , 'bar' ]); ~~~ ### [](http://packagist.p2hp.com/packages/predis/predis#user-content-script-commands)脚本命令 虽然可以直接使用and在 Redis 2.6+ 上利用[Lua 脚本](http://redis.io/commands/eval),但 Predis 提供脚本命令作为构建在它们之上的更高级别的抽象,以使事情变得简单。脚本命令可以在客户端使用的命令工厂中注册,并且可以像普通 Redis 命令一样访问,但它们定义了传输到服务器以进行远程执行的 Lua 脚本。在内部,它们默认使用并通过其 SHA1 哈希标识脚本以节省带宽,但在需要时用作备用:[`EVAL`](http://redis.io/commands/eval)[`EVALSHA`](http://redis.io/commands/evalsha)[`EVALSHA`](http://redis.io/commands/evalsha)[`EVAL`](http://redis.io/commands/eval) ~~~ // 通过扩展 Predis\Command\ScriptCommand 定义一个新的脚本命令: class ListPushRandomValue extends Predis \ Command \ ScriptCommand { 公共 函数 getKeysCount () { 返回 1 ; } 公共 函数 getScript () { return <<<LUA math.randomseed(ARGV[1]) local rnd = tostring(math.random()) redis.call('lpush', KEYS[1], rnd) return rnd LUA ; } } // 在当前命令工厂注入脚本命令: $ client = new Predis \ Client ( $ parameters , [ 'commands' => [ 'lpushrand' => 'ListPushRandomValue' , ], ]); $ response = $ client -> lpushrand ( 'random_values' , $ seed = mt_rand ()); ~~~ ### [](http://packagist.p2hp.com/packages/predis/predis#user-content-customizable-connection-backends)可定制的连接后端 Predis 可以使用不同的连接后端连接到 Redis。其中两个利用了第三方扩展,例如[phpiredis](https://github.com/nrk/phpiredis),从而获得了显着的性能提升,尤其是在处理大型多批量响应时。一种基于 PHP 流,另一种基于`ext-socket`.两者都支持 TCP/IP 和 UNIX 域套接字: ~~~ $ client = new Predis \ Client ( 'tcp://127.0.0.1' , [ 'connections' => [ 'tcp' => 'Predis\Connection\PhpiredisStreamConnection' , // PHP 流资源 'unix' => 'Predis \Connection\PhpiredisSocketConnection' , // ext-socket 资源 ], ]); ~~~ 通过为客户端选项指定描述性字符串,客户端也可以配置为依赖于[ppiredis](https://github.com/nrk/phpiredis)`connections`\-backend 。支持的字符串值是: * `phpiredis-stream`地图`tcp`,`redis`以及`unix`\_`Predis\Connection\PhpiredisStreamConnection` * `phpiredis-socket`地图`tcp`,`redis`以及`unix`\_`Predis\Connection\PhpiredisSocketConnection` * `phpiredis`只是一个别名`phpiredis-stream` ~~~ $ client = new Predis \ Client ( 'tcp://127.0.0.1' , [ 'connections' => 'phpiredis' ]); ~~~ 开发人员可以创建自己的连接类来支持全新的网络后端、扩展现有类或提供完全不同的实现。连接类必须实现`Predis\Connection\NodeConnectionInterface`或扩展`Predis\Connection\AbstractConnection`: ~~~ MyConnectionClass 类实现 Predis \ Connection \ NodeConnectionInterface { // 实现在这里... } // 使用 MyConnectionClass 处理 `tcp` 方案的连接: $ client = new Predis \ Client ( 'tcp://127.0.0.1' , [ 'connections' => [ 'tcp' => 'MyConnectionClass' ], ]); ~~~ 要更深入地了解如何创建新的连接后端,您可以参考`Predis\Connection`命名空间中可用的标准连接类的实际实现。 ## [](http://packagist.p2hp.com/packages/predis/predis#user-content-development)发展 ### [](http://packagist.p2hp.com/packages/predis/predis#user-content-reporting-bugs-and-contributing-code)报告错误和贡献代码 对 Predis 的贡献受到高度赞赏,无论是以对新功能、错误修复或错误报告的拉取请求的形式。我们只要求您在提交更改或在问题跟踪器上提交错误之前遵守一[组基本规则](https://github.com/predis/predis/blob/HEAD/CONTRIBUTING.md),以使每个人在项目工作时更容易保持一致。 ### [](http://packagist.p2hp.com/packages/predis/predis#user-content-test-suite)测试套件 **注意**:永远不要针对在生产环境中运行或包含您感兴趣的数据的 Redis 实例运行 Predis 附带的测试套件! Predis 有一个全面的测试套件,涵盖了库的各个方面,并且可以选择对正在运行的 Redis 实例执行集成测试(需要 >= 2.4.0 以验证每个命令实现的正确行为。不支持的集成测试Redis 命令会自动跳过。如果您没有启动并运行 Redis,则可以禁用集成测试。有关测试此库的更多详细信息,请参阅[测试自述文件。](https://github.com/predis/predis/blob/HEAD/tests/README.md) Predis 使用 GitHub Actions 进行持续集成,过去和当前构建的历史可以[在其操作页面上](https://github.com/predis/predis/actions)找到。