Перейти к содержимому
docs.
WORKSPACE

Документации проектов

Открыть каталог проектов
Localzet ServerАсинхронный PHP-серверTriangleФреймворк и компонентыMIX IDИдентификация и интеграцииHack APIПубличные API хакатонаACNПроект и компонентыUserlay / UserNetПроект и компонентыAxiomПроект и компонентыМесседжинг через почтуПроект и компонентыLWT / JWT / JOSEПроект и компонентыФинансовая аналитика KimaiПроект и компонентыМультипарадигмальная БДПроект и компонентыZorin PlatformПроект и компонентыZorin TrustПроект и компонентыFloraScope / VegwatchПроект и компонентыaegis-qДокументация проектаaevumdbДокументация проектаauditДокументация проектаauto-invest-managerАвтотрейдерcaine-companionДокументация проектаcertbot-cloudflareДокументация проектаClusterLocalzet Server / ClustercmdveilДокументация проектаConsolePHP CLICronБиблиотеки Localzet Serverdata-connectorДокументация проектаdevice-controlDevice Controlenn-projectДокументация проектаEventsБиблиотеки Localzet ServerflowsintДокументация проектаforgeДокументация проектаHttpClientБиблиотеки Localzet ServerinterpreterСобственный языкinvariaДокументация проектаkeynotesДокументация проектаknotrouteKnotroutelaravel-personal-analyticsДокументация проектаlocalzet-osДокументация проектаmeridianДокументация проектаMQTTБиблиотеки Localzet Servernano-kernelСобственная ОСNoterДокументация проектаpersonal-analyticsДокументация проектаProxyБиблиотеки Localzet ServerPSRБиблиотеки Localzet ServerPSR-7Библиотеки Localzet Serverrschs-monitorДокументация проектаsemsealДокументация проектаshardsealДокументация проектаSocketIOБиблиотеки Localzet ServerSOCKS5Библиотеки Localzet Serverstandalone-analyticsДокументация проектаstatic-php-cliДокументация проектаStorageБиблиотеки Localzet Server✓sutureДокументация проектаtempoweaveДокументация проектаttsСинтез речиTunnelБиблиотеки Localzet Serverui-kitUI KitvesperДокументация проектаWebAnalyzerWebAnalyzerzorin-access-brokerДокументация проектаzorin-authority-brokerДокументация проектаzorin-authority-sdk-phpДокументация проектаzorin-authority-sdk-pythonДокументация проектаzorin-authority-sdk-tsДокументация проектаzorin-client-intelДокументация проектаzorin-device-core-aospДокументация проектаzorin-host-agentДокументация проектаzorin-native-labДокументация проектаzorin-nodeДокументация проектаzorin-opsДокументация проектаdonstu-python-sdkДокументация проектаfloortraceFloortraceserver-rsLocalzet Server / Cluster
Каталог

Storage — общее хранилище значений в памяти отдельного PHP-процесса. Приложение обращается к нему через TCP-клиент localzet\Storage\Client; сервер localzet\Storage\Server выполняет команды над массивом данных.

Так можно обмениваться короткоживущим состоянием между worker-процессами. Данные исчезают при перезапуске сервера. Дискового журнала, TTL, репликации и восстановления после сбоя в реализации нет.

Манифест требует PHP ^8.2 и Localzet Server ^4.1:

Окно терминала
composer config repositories.localzet-storage vcs https://github.com/localzet/Storage
composer require localzet/storage:dev-main

Зависимость от Server 4.x относится к этому пакету. Не считайте его совместимым с другой major-версией только из-за совпадения namespace.

use localzet\Storage\Server;
require __DIR__ . '/vendor/autoload.php';
new Server('127.0.0.1', 8008);
\localzet\Server::runAll();

Сервер создаёт один worker с протоколом frame, именем StorageServer и отключённым reload. Один процесс нужен потому, что данные хранятся в обычном массиве объекта: несколько независимых процессов не разделят его автоматически.

Укажите адрес явно. Значение конструктора по умолчанию — 0.0.0.0:8008. Аутентификация, TLS и проверка права на отдельный ключ в обработчике отсутствуют. Сервер вызывает unserialize() без запрета классов; клиент также десериализует ответ. Обе стороны должны доверять друг другу и транспорту. Не открывайте этот сервис для пользовательских подключений или в интернет.

use localzet\Storage\Client;
$storage = new Client('127.0.0.1:8008');
$storage->set('article:42', ['title' => 'Example']);
$article = $storage->get('article:42');
$storage->delete('article:42');

Клиент подключается лениво, при первой операции с ключом. Передавайте адрес без tcp://: префикс клиент добавляет сам. Соединение сохраняется и используется для следующих операций, пока остаётся открытым.

Все операции клиента блокирующие: запись и чтение выполняются через fwrite() и fread(). Если вызвать их из callback асинхронного Server, этот worker будет ждать ответ хранилища и не сможет в это время обслуживать другие события.

Ключи лучше задавать непустыми строками. Значения передаются через PHP serialize(): формат предназначен для PHP-клиентов с согласованными типами и версиями классов. Для межъязыкового API это не готовый JSON-протокол.

$created = $storage->add('job:42', ['state' => 'queued']);

add() возвращает true, если ключ ещё не определён, и false, если уже есть. Проверка использует isset(): сохранённое null считается отсутствием. Поэтому add('key', $value) может заменить ранее установленное null.

У операции нет TTL. Такой ключ сам не освободится после падения владельца, поэтому без дополнительного механизма срока действия его нельзя использовать как полноценную блокировку задания.

$storage->add('downloads:42', 0);
$count = $storage->increment('downloads:42');
$count = $storage->increment('downloads:42', 5);

increment() не создаёт отсутствующий счётчик: возвращает false. Существующее нечисловое значение сначала заменяется на 0, затем прибавляется шаг. Числовая строка считается числом по правилам PHP. Отрицательный шаг допустим как уменьшение значения.

Ответом является новое значение, которое может быть 0; проверяйте отказ через === false, а не через if (!$count).

Обновление с проверкой прежнего значения

Заголовок раздела «Обновление с проверкой прежнего значения»
$old = $storage->get('job:42');
$new = ['state' => 'running'];
if (!$storage->cas('job:42', $old, $new)) {
// Another writer changed the value; read it again before retrying.
}

CAS сравнивает md5(serialize($old)) с сериализацией текущего значения на сервере. Если они совпали, сохраняет новое значение и возвращает true; иначе — false.

Для массивов важны порядок и типы элементов, для объектов — результат PHP-сериализации. Это сравнение состояния, а не проверка подлинности сообщения. MD5 здесь не защищает от недоверенного клиента.

Отсутствующий ключ сравнивается как null, поэтому cas($key, null, $value) способен создать значение. Несколько последовательных CAS над разными ключами не образуют транзакцию.

$storage = new Client([
'127.0.0.1:8008',
'127.0.0.1:8009',
]);

Клиент выбирает сервер по остатку CRC32 ключа от числа адресов. Один ключ направляется ровно на один сервер; копирования на остальные нет. При отказе выбранного сервера клиент не переключается на соседний.

Порядок адресов и их количество являются частью размещения данных. Их изменение перенаправит ключи без переноса прежних значений. Для стабильной работы все клиенты должны использовать одинаковый список в одинаковом порядке.

$storage->timeout = 2;
$storage->pingInterval = 25;

timeout используется при установлении соединения и как socket timeout. Настройте его до первого запроса: уже открытое соединение не перенастраивается при изменении поля.

Ошибка соединения выбрасывает Exception с сообщением socket API; неполная запись — Exception('write fail'); пустой/неудачный ответ — Exception('read fail'). Это не отдельная типизированная иерархия ошибок протокола. Автоматического повторения команды нет. После потери ответа нельзя по одному исключению понять, успел ли сервер применить запись.

Если доступен localzet\Timer и клиент работает в CLI, при подключении регистрируется ping-timer. Он работает только при реально запущенном Timer/event loop. Ping не запрашивает подтверждение от сервера и не доказывает, что ключи сохранены. Если запись ping не удалась, соединение закрывается и timer удаляется.

Полный контракт операций и формата сообщений

Исходный код · AGPL-3.0