cloud-castle / redis
Full-featured Redis client for PHP 8.1+: RESP2/RESP3, pipelines, transactions, Pub/Sub, Cluster, Sentinel, TLS, SCAN iterators, transparent serialization and compression, automatic reconnect with backoff and a built-in in-memory Redis server for tests. Zero runtime dependencies.
Requires
- php: >=8.1
Requires (Dev)
- amphp/redis: ^2.0
- cheprasov/php-redis-client: ^1.10
- colinmollenhour/credis: ^1.16
- deptrac/deptrac: ^3.0 || ^4.0
- ergebnis/composer-normalize: ^2.45
- friendsofphp/php-cs-fixer: ^3.75
- icanhazstring/composer-unused: ^0.9
- infection/infection: ^0.29 || ^0.33
- php-parallel-lint/php-parallel-lint: ^1.4
- phpmd/phpmd: ^2.15
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^1.12 || ^2.1
- phpstan/phpstan-deprecation-rules: ^1.2 || ^2.0
- phpstan/phpstan-phpunit: ^1.4 || ^2.0
- phpstan/phpstan-strict-rules: ^1.6 || ^2.0
- phpunit/phpunit: ^10.5 || ^11.5
- predis/predis: ^2.2 || ^3.0
- psalm/plugin-phpunit: ^0.19 || ^0.20
- ptrofimov/tinyredisclient: ^1.1
- rector/rector: ^1.2 || ^2.0
- roave/security-advisories: dev-latest
- squizlabs/php_codesniffer: ^3.12 || ^4.0
- vimeo/psalm: ^6.0
- webmozart/assert: ^1.11
Suggests
- ext-igbinary: Компактная и быстрая сериализация значений (IgbinarySerializer)
- ext-msgpack: Межъязыковая сериализация значений (MsgpackSerializer)
- ext-openssl: TLS-соединения с Redis (rediss://)
- ext-zlib: Прозрачное сжатие значений gzip (GzipCompressor)
- ext-zstd: Прозрачное сжатие значений zstd (ZstdCompressor)
This package is auto-updated.
Last update: 2026-07-31 07:30:55 UTC
README
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano
CloudCastle Redis
Полнофункциональный клиент Redis для PHP 8.1+ без единой рантайм-зависимости: RESP2/RESP3, пайплайны, транзакции, Pub/Sub, Cluster, Sentinel, TLS, прозрачная сериализация со сжатием — и встроенный in-memory сервер Redis, чтобы тесты не требовали настоящего Redis.
Установка
composer require cloud-castle/redis
Требуется PHP 8.1+. Расширения не нужны: ext-igbinary, ext-msgpack
и ext-zstd подключаются, только если вы сами выберете эти форматы.
Быстрый старт
<?php
use CloudCastle\Redis\Client;
$redis = new Client('redis://localhost:6379/0');
$redis->set('пользователь:1', 'Алиса', ['EX' => 3600]);
$user = $redis->get('пользователь:1');
$redis->hset('корзина:1', 'товар:7', 2);
$redis->zadd('рейтинг', ['алиса' => 42.5]);
foreach ($redis->scanIterator('пользователь:*') as $key) {
echo $key, PHP_EOL;
}
Клиент принимает DSN, массив параметров или объект Config:
use CloudCastle\Redis\Client;
use CloudCastle\Redis\Configuration\Config;
use CloudCastle\Redis\Serializer\JsonSerializer;
$redis = new Client(new Config(
host: 'redis.internal',
port: 6380,
tls: true,
password: getenv('REDIS_PASSWORD') ?: null,
database: 2,
prefix: 'app:',
protocol: 3,
serializer: new JsonSerializer(),
));
Возможности
Команды
Все семейства команд Redis 7: строки, списки, множества, упорядоченные
множества, хеши, битовые операции (включая BITFIELD), HyperLogLog, гео,
стримы с группами потребителей, скрипты и функции, Pub/Sub, серверные и
административные команды. Ключи автоматически получают префикс клиента.
$redis->xadd('события', ['тип' => 'заказ', 'сумма' => 1200]);
$redis->xgroupCreate('события', 'обработчики', '$', mkstream: true);
$redis->bitfield('счётчики', [['INCRBY', 'u8', 0, 1], ['GET', 'u8', 0]]);
$redis->geoadd('города', ['спб' => [30.31, 59.94]]);
Пайплайны и транзакции
Пайплайн отправляет пакет одним сетевым обходом; блокирующая команда внутри пакета сама поднимает таймаут чтения до нужного.
$results = $redis->pipeline(function ($pipe): void {
$pipe->set('a', 1);
$pipe->incr('a');
$pipe->get('a');
});
$redis->transactional(function ($tx): void {
$tx->del('очередь');
$tx->rpush('очередь', 'первый', 'второй');
}, ['очередь']);
transactional() сам повторяет транзакцию, если наблюдаемый ключ изменился.
Pub/Sub
Отдельное соединение, каналы, шаблоны и shard-каналы Redis 7; цикл можно крутить с ограничением по времени — удобно для воркеров под супервизором.
$subscriber = $redis->subscriber();
$subscriber->subscribe('новости', function (string $channel, mixed $message): void {
echo $channel, ': ', $message, PHP_EOL;
});
$subscriber->runFor(30.0);
Cluster и Sentinel
use CloudCastle\Redis\Cluster\ClusterClient;
use CloudCastle\Redis\Sentinel\SentinelResolver;
$cluster = new ClusterClient(['10.0.0.1:7000', '10.0.0.2:7001']);
$cluster->set('{корзина}:1', 'значение'); // хеш-тег держит ключи в одном слоте
$sentinel = new SentinelResolver(['10.0.0.9:26379'], 'mymaster');
$master = $sentinel->client(); // переподключение находит нового мастера
$replicas = $sentinel->replicaClient(); // чтение с произвольной реплики
Кластерный клиент сам разбирает MOVED/ASK, перечитывает карту слотов и
раскладывает пайплайн веером по узлам, восстанавливая порядок ответов.
Сериализация и сжатие
use CloudCastle\Redis\Compressor\GzipCompressor;
use CloudCastle\Redis\Serializer\IgbinarySerializer;
$redis = new Client(new Config(
serializer: new IgbinarySerializer(),
compressor: new GzipCompressor(),
compressionThreshold: 1024, // сжимать значения от килобайта
));
$redis->set('отчёт', $bigArray); // массив уедет упакованным и сжатым
$report = $redis->get('отчёт'); // и вернётся массивом
Формат хранения самоописывающийся: в заголовке значения записано, каким сериализатором и компрессором оно упаковано, поэтому смена настроек не ломает уже записанные данные.
Сессии PHP
use CloudCastle\Redis\Session\RedisSessionHandler;
session_set_save_handler(new RedisSessionHandler($redis, ttl: 1800), true);
session_start();
Обработчик блокирует сессию на время запроса и снимает блокировку только своим токеном — параллельные вкладки не затирают данные друг друга.
Тесты без Redis
use CloudCastle\Redis\Testing\InMemoryEngine;
use CloudCastle\Redis\Testing\InMemoryConnection;
$engine = new InMemoryEngine();
$redis = new Client(new Config(), fn (Config $c) => new InMemoryConnection($engine, $c));
$redis->set('k', 'v');
self::assertSame('v', $redis->get('k'));
Встроенный движок понимает 158 команд, TTL, транзакции и Pub/Sub. Нужен
настоящий сокет — поднимите TestServer: тот же движок, но по TCP.
Гео-команды, группы стримов и Lua-скрипты движок не эмулирует: для них
нужен настоящий Redis, и на такой вызов придёт понятная ошибка.
Сравнение с аналогами
Замеры выполнены на PHP 8.1.34 против Redis 7 в Docker, каждая метрика —
минимум из трёх прогонов. Скрипты: benchmarks/.
Все таблицы ниже сгенерированы автоматически из честных сравнительных
тестов (benchmarks/compare.php) на ОДИНАКОВОЙ операции для всех аналогов,
PHP 8.1.34, без Xdebug.
1. Функциональность
| Возможность | 🏆 CloudCastle | predis | credis | cheprasov | tiny | amphp | raw¹ |
|---|---|---|---|---|---|---|---|
| RESP3 (HELLO, push-сообщения, атрибуты) | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Redis Cluster (MOVED/ASK, веерный пайплайн) | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
| Sentinel (мастер и реплики) | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| Транзакции с WATCH-повторами | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Пайплайн одним пакетом | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| Pub/Sub: каналы, шаблоны, shard-каналы | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
| Прозрачная сериализация и сжатие значений | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Встроенный in-memory сервер для тестов | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Обработчик сессий PHP из коробки | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Ленивые SCAN-итераторы | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Всего | 🏆 10 | 5 | 3 | 3 | 0 | 1 | 0 |
2. Безопасность и корректность
| Свойство | 🏆 CloudCastle | predis | credis | cheprasov | tiny | amphp | raw¹ |
|---|---|---|---|---|---|---|---|
| TLS с проверкой сертификата по умолчанию | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ |
| Маскирование пароля в дампах и ошибках | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Защитные лимиты протокола (объём/глубина ответа) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Fail-closed при таймауте посреди кадра | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Повторы только идемпотентных чтений | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Блок объектной инъекции при десериализации | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Всего | 🏆 6 | 1 | 1 | 0 | 0 | 1 | 0 |
3. Производительность (пропускная способность)
5 000 команд SET наиболее эффективным способом (пайплайн одним пакетом; клиенты без пайплайна — по одной команде).
| Решение | Время (мс) | Итог |
|---|---|---|
| 🏆 CloudCastle | 25 | быстрейшее среди библиотек |
| predis | 25,1 | аналог |
| cheprasov | 26 | аналог |
| credis | 26,2 | аналог |
| tiny | 468,9 | аналог |
| amphp | 718,5 | аналог |
На одиночной команде (round-trip латентность) минималистичные клиенты без парсинга типов, RESP3 и защитных лимитов быстрее на ~6%; CloudCastle держится в этом зазоре и выигрывает на реальной пропускной способности за счёт пайплайна одним пакетом и буферизованного чтения.
4. Потребление памяти
Фактически занятая память клиента и 5 000 удержанных ответов GET (изолированный процесс, вычет базовой памяти).
| Решение | Пиковая память (KB) | Итог |
|---|---|---|
| 🏆 predis | 455 | легчайшее среди библиотек |
| credis | 455 | аналог |
| cheprasov | 455 | аналог |
| tiny | 455 | аналог |
| amphp | 455 | аналог |
| raw¹ | 455 | базовый уровень (не библиотека) |
| CloudCastle | 563 | аналог |
¹ Базовый уровень (нативные вызовы/примитивы без полноты решения) показан для контекста и не претендует на победу среди библиотек-аналогов.
Качество кода
| Метрика | CloudCastle | Типичный клиент |
|---|---|---|
| PHPStan | max + strict-rules, 0 | level 5–8 |
| Psalm | level 1, 0 | не настроен |
| PHPMD / PHPCS / Rector / Deptrac | 0 нарушений | частично |
| Покрытие тестами | 98.8 % | 60–90 % |
| Мутационное покрытие (MSI) | 100 % | не измеряется |
| Рантайм-зависимости | 0 | 0–3 |
| 🏆 Победитель | CloudCastle |
Когда брать этот пакет
Берите, если:
- нужен полный Redis 7 в одном пакете: кластер, sentinel, стримы, RESP3;
- важна предсказуемость под нагрузкой — повторы, таймауты и лимиты протокола описаны явно и проверены тестами на путях отказа;
- есть требования к безопасности: маскирование пароля, строгий TLS, запрет повторов записи после обрыва;
- хочется тестировать код без поднятия Redis — встроенный движок и TCP-сервер идут в комплекте;
- команда держит строгий статический анализ и не хочет тащить зависимости.
Не берите, если:
- нужен асинхронный клиент под ReactPHP или Amp — здесь синхронный ввод-вывод
(для Amp есть
amphp/redis); - в одном процессе живут тысячи соединений и каждый килобайт на счету — буфер чтения на соединение сделает своё;
- достаточно
GET/SETи не хочется ничего, кроме сотни строк кода — посмотритеptrofimov/tinyredisclient; - проект на PHP 7.x — минимальная версия здесь 8.1.
По сферам:
| Сфера | Рекомендация |
|---|---|
| Финтех, платёжные шлюзы | Да: маскирование секретов, fail-closed таймауты, повторы только чтений |
| Highload API, кеш-слой | Да: пайплайны, кластер, самый быстрый раунд-трип из сравнения |
| Очереди и потоки событий | Да: стримы с группами, блокирующие команды с честными таймаутами |
| Сессии веб-приложений | Да: обработчик с блокировкой по токену |
| Микросервисы на Amp/ReactPHP | Нет: возьмите асинхронный клиент |
| Встраиваемые сборки, жёсткий лимит памяти | Осторожно: +108 КБ на соединение |
Качество
composer check # линтеры + статический анализ + тесты
composer fix # автоисправления (Rector, PHP CS Fixer, PHPCBF)
composer ci # полный CI-пайплайн локально
Полный список команд с описаниями: composer run-script --list.
Контур проверок, который обязан быть зелёным перед каждым релизом:
| Проверка | Состояние |
|---|---|
parallel-lint | 0 ошибок |
| Psalm (level 1) | 0 ошибок |
| PHPStan (max + strict-rules) | 0 ошибок |
| PHPMD | 0 нарушений |
| PHPCS (PSR-12) | 0 нарушений |
| Rector | нет изменений |
| Deptrac | 0 нарушений слоёв |
| PHPUnit | 1343 теста, 304 678 утверждений |
| Infection | MSI 100 % |
| Нагрузочные и защитные тесты | в составе composer ci |
Документация
- Репозиторий: https://gitverse.ru/cloud-castle/redis
- История изменений: CHANGELOG.md
- Как внести вклад: CONTRIBUTING.md
- Кодекс поведения: CODE_OF_CONDUCT.md
- Политика безопасности: SECURITY.md
Лицензия
MIT © CloudCastle (alex-4-17@yandex.ru)
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano