fiberphp/redis

FiberPHP Redis client manager: sync/async drivers, RESP protocol, heartbeat keepalive and auto-reconnect.

Maintainers

Package info

gitee.com/FiberPHP/redis

Issues

pkg:composer/fiberphp/redis

Transparency log

Statistics

Installs: 2

Dependents: 1

Suggesters: 0

dev-master 2026-08-22 08:10 UTC

This package is not auto-updated.

Last update: 2026-08-22 11:34:33 UTC


README

FiberPHP 框架的 Redis 客户端子包。提供同步(Sync)和异步(Async)双驱动客户端,实现 RESP 协议编解码,支持心跳保活、断线自动重连、协程挂起/恢复,通过 config/redis.php 声明式管理多连接。

特性

  • 双驱动:Sync 基于 ext-redis 同步阻塞;Async 基于 Workerman AsyncTcpConnection 非阻塞
  • RESP 协议:自实现 RESP3 编解码器,支持简单字符串、错误、整数、批量字符串、数组
  • 心跳保活:Sync 通过 Timer::add 定期 ping,防止连接被 Redis 主动断开
  • 自动重连:Sync 命令异常时按指数退避重试(最多 3 次);Async 断线后延迟 5s 自动重连
  • 协程挂起:Async 在 revolt/event-loop 可用时,命令调用自动挂起当前协程,响应到达后恢复,使异步 Redis 调用像同步代码一样书写
  • 订阅模式:Async 支持 subscribe / pSubscribe 频道和模式订阅
  • 连接探活RedisProvider 启动时 ping 探活,fail_fast=true 时探活失败终止 Worker 启动
  • 多连接:通过 config/redis.php 声明 default 及更多命名连接(cache / queue 等由应用层按需添加)

环境要求

  • PHP >= 8.3
  • ext-redis
  • fiberphp/framework dev-master

安装

composer require fiberphp/redis

安装后 PackageInstaller::discover 自动把 config/redis.php 拷贝到应用 config/redis.php(幂等不覆盖),并通过 PackageManifest 注册 RedisProvider

配置

config/redis.php

return [
    // 默认连接
    'default' => [
        'host'            => env('REDIS_HOST', '127.0.0.1'),
        'port'            => env('REDIS_PORT', 6379),
        'auth'            => env('REDIS_AUTH'),
        'db'              => 0,
        'connect_timeout' => 2,
        'wait_timeout'    => 600,   // 异步命令等待超时(秒,仅 Async)
        'ping'            => 55,    // 心跳间隔(秒,仅 Sync)
        'ssl'             => false,
    ],
    // 按需声明更多连接(cache / queue 等业务连接由应用层定义,建议分 db 隔离)
    // 'cache' => ['host' => env('REDIS_HOST', '127.0.0.1'), 'db' => 1, ...],
    // 探活失败是否终止启动(Redis 是基础设施,默认终止)
    'fail_fast' => true,
];
字段SyncAsync说明
hostRedis 主机地址
portRedis 端口
auth认证密码(无密码留空)
db默认数据库编号
connect_timeout连接超时(秒)
wait_timeout异步命令等待超时(秒)
ping心跳间隔(秒)
ssl是否启用 TLS

使用

同步客户端

// 获取 RedisManager → 创建 sync 客户端
$redis = redis()->sync();              // default 连接
$cache = redis()->sync('cache');      // cache 连接(需在 config/redis.php 声明)

// 直接调用 Redis 命令(通过 __call 代理到 ext-redis)
$redis->set('foo', 'bar');
$value = $redis->get('foo');
$redis->del('key1', 'key2');

// 闭包形式(等价)
$value = redis()->sync()->get('foo');

异步客户端(回调模式)

// 回调模式:命令执行后回调通知
$redis = redis()->async();

$redis->get('foo', function ($result, $client) {
    echo $result;  // 'bar'
});

$redis->set('counter', 1, function ($result) {
    // $result === true
});

异步客户端(协程模式)

协程模式下(revolt/event-loop 已加载),不传回调时命令自动挂起当前协程,响应到达后恢复,书写方式与同步一致:

$redis = redis()->async();

// 挂起 → 等待响应 → 恢复,返回结果
$value = $redis->get('foo');

// 链式调用
$count = $redis->incr('counter');
$redis->set("user:{$count}", 'data');

订阅模式

$redis = redis()->async();

// 频道订阅
$redis->subscribe(['news', 'alerts'], function ($channel, $message, $client) {
    echo "[{$channel}] {$message}\n";
});

// 模式订阅(通配符)
$redis->pSubscribe(['user:*'], function ($pattern, $channel, $message, $client) {
    echo "[{$channel}] {$message}\n";
});

BRPOP 阻塞弹出

// 协程模式:挂起直到有消息或超时
$result = redis()->async()->brPop(['queue:email'], 0);  // 0 = 无限阻塞
if ($result) {
    [$key, $value] = $result;
    // 处理消息...
}

SCAN 增量扫描

// 不阻塞 Redis,适合大库扫描
$keys = redis()->sync()->scanKeys('prefix:*', 100);  // 每次提示 100 条
foreach ($keys as $key) {
    // ...
}

获取原生 Redis 实例

$native = redis()->sync()->getRedis();
$native->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP);
$native->setOption(\Redis::OPT_PREFIX, 'app:');

Sync vs Async

SyncAsync
底层ext-redis(同步阻塞)Workerman AsyncTcpConnection(非阻塞)
协程不支持(同步调用)支持 revolt/event-loop 挂起/恢复
心跳Timer::add 定期 ping无(命令队列驱动)
重连指数退避重试 3 次延迟 5s 自动重连
超时connect_timeoutconnect_timeout + wait_timeout
订阅不支持subscribe / pSubscribe
BRPOP不支持支持(协程挂起)
适用简单场景 / CLI 脚本Worker 内 / 高并发 / 订阅

启动探活

RedisProvider 在 Worker 启动时对 default 连接做 ping 探活:

  • fail_fast = true(默认):探活失败终止 Worker 启动(Redis 是基础设施)
  • fail_fast = false:探活失败仅记录日志,运行时首次命令才会抛异常

超时保护由 BootGuard 通过 pcntl_alarm 统一兜底。

自定义实现

通过 setSyncClass / setAsyncClass 替换实现类(如追踪包装类):

$manager = redis();
$manager->setSyncClass(MyTracingSync::class);
$manager->setAsyncClass(MyTracingAsync::class);

替换类需分别继承 Sync / Async

License

MIT