PHPackages                             beeline/yii2-resilient-mutex - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. beeline/yii2-resilient-mutex

ActiveYii2-extension[Utility &amp; Helpers](/categories/utility)

beeline/yii2-resilient-mutex
============================

Fault-tolerant mutex with circuit breaker pattern and automatic backend switching for Yii2

1.0.5(6mo ago)00LGPL-3.0-or-laterPHPPHP ^8.4CI passing

Since Nov 7Pushed 6mo agoCompare

[ Source](https://github.com/pozitronik/yii2-resilient-mutex)[ Packagist](https://packagist.org/packages/beeline/yii2-resilient-mutex)[ RSS](/packages/beeline-yii2-resilient-mutex/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (3)Versions (7)Used By (0)

Отказоустойчивый Mutex для Yii2
===============================

[](#отказоустойчивый-mutex-для-yii2)

[![Tests](https://github.com/pozitronik/yii2-resilient-mutex/actions/workflows/tests.yml/badge.svg)](https://github.com/pozitronik/yii2-resilient-mutex/actions/workflows/tests.yml)[![Codecov](https://camo.githubusercontent.com/d3e5877cb03d7f21f33380b46c3a0fab99558aee8204614ea9517a4ef69c51a8/68747470733a2f2f636f6465636f762e696f2f67682f706f7a6974726f6e696b2f796969322d726573696c69656e742d6d757465782f6272616e63682f6d61737465722f67726170682f62616467652e737667)](https://codecov.io/gh/pozitronik/yii2-resilient-mutex)[![Packagist Version](https://camo.githubusercontent.com/ed278481aaf18c6274fd808954f4fcd1600cd32226432b35c37308062789766f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6265656c696e652f796969322d726573696c69656e742d6d75746578)](https://packagist.org/packages/beeline/yii2-resilient-mutex)[![Packagist License](https://camo.githubusercontent.com/2167f762d4f13876356129ece8555741445aaaf821e1c9c062d244f369f5471c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6265656c696e652f796969322d726573696c69656e742d6d75746578)](https://packagist.org/packages/beeline/yii2-resilient-mutex)[![Packagist Downloads](https://camo.githubusercontent.com/3d91c8d068d6da907578e2a2792d7a5f3751ce43ed0de5860e75cb786e6876bc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6265656c696e652f796969322d726573696c69656e742d6d75746578)](https://packagist.org/packages/beeline/yii2-resilient-mutex)

Отказоустойчивый mutex с паттерном Circuit Breaker и автоматическим переключением между бэкендами для Yii2. Обеспечивает высокую доступность распределённых блокировок.

Возможности
-----------

[](#возможности)

- **Автоматическое переключение между бэкендами**: Бесшовный переход на резервные механизмы блокировок при сбоях
- **Интеграция Circuit Breaker**: Каждый бэкенд имеет собственный circuit breaker для предотвращения каскадных сбоев
- **Две стратегии повторов**: RETRY\_PER\_BACKEND и RETRY\_GLOBAL для различных сценариев
- **Отслеживание блокировок**: Запоминает, какой бэкенд захватил каждую блокировку для корректного освобождения
- **Мониторинг работоспособности**: Информация о состоянии и статистике бэкендов в реальном времени

Установка
---------

[](#установка)

```
composer require beeline/yii2-resilient-mutex
```

Требования
----------

[](#требования)

- PHP &gt;= 8.4
- Yii2 &gt;= 2.0.45
- beeline/yii2-circuit-breaker &gt;= 1.0

Использование
-------------

[](#использование)

### Базовая конфигурация

[](#базовая-конфигурация)

```
use beeline\ResilientMutex\ResilientMutex;
use yii\redis\Mutex as RedisMutex;
use yii\mutex\PgsqlMutex;

return [
    'components' => [
        'mutex' => [
            'class' => ResilientMutex::class,
            'backends' => [
                // Первичный бэкенд: Redis
                [
                    'mutex' => [
                        'class' => RedisMutex::class,
                        'redis' => 'redis',
                    ],
                    'retries' => 3,
                    'retryDelay' => 50, // миллисекунды
                    'circuitBreaker' => [
                        'failureThreshold' => 0.5,
                        'windowSize' => 10,
                        'timeout' => 30,
                    ],
                ],
                // Резервный бэкенд: PostgreSQL
                [
                    'mutex' => [
                        'class' => PgsqlMutex::class,
                        'db' => 'db',
                    ],
                    'retries' => 2,
                    'retryDelay' => 100,
                    'circuitBreaker' => [
                        'failureThreshold' => 0.7,
                        'windowSize' => 5,
                        'timeout' => 60,
                    ],
                ],
            ],
            'retryStrategy' => ResilientMutex::RETRY_PER_BACKEND,
        ],
    ],
];
```

### Простое использование

[](#простое-использование)

```
use Yii;

$mutex = Yii::$app->mutex;

// Автоматическое переключение между бэкендами
if ($mutex->acquire('my_lock', 5)) {
    try {
        // Критическая секция
        performCriticalOperation();
    } finally {
        $mutex->release('my_lock');
    }
}
```

Конфигурация
------------

[](#конфигурация)

### Параметры бэкенда

[](#параметры-бэкенда)

ПараметрТипОписание`mutex`Mutex|arrayЭкземпляр Mutex или конфигурация для создания`retries`intКоличество повторов для этого бэкенда`retryDelay`intМиллисекунды между повторами`circuitBreaker`array|nullКонфигурация circuit breaker для этого бэкенда### Стратегии повторов

[](#стратегии-повторов)

#### RETRY\_PER\_BACKEND (по умолчанию)

[](#retry_per_backend-по-умолчанию)

Пытается N раз на каждом бэкенде перед переходом к следующему:

```
'retryStrategy' => ResilientMutex::RETRY_PER_BACKEND,
'backends' => [
    ['mutex' => [...], 'retries' => 3],  // 3 попытки на Redis
    ['mutex' => [...], 'retries' => 2],  // 2 попытки на PostgreSQL
],
```

#### RETRY\_GLOBAL

[](#retry_global)

Всего N попыток по всем бэкендам:

```
'retryStrategy' => ResilientMutex::RETRY_GLOBAL,
'globalRetries' => 10,  // Всего 10 попыток на все бэкенды
```

Мониторинг
----------

[](#мониторинг)

### Проверка состояния бэкендов

[](#проверка-состояния-бэкендов)

```
$mutex = Yii::$app->mutex;

// Получить состояние всех бэкендов
$status = $mutex->getBackendStatus();

foreach ($status as $backend) {
    echo "Бэкенд #{$backend['index']}: {$backend['class']}\n";
    echo "Состояние: {$backend['state']}\n"; // closed, open, half_open
    echo "Отказов: {$backend['stats']['failures']}/{$backend['stats']['total']}\n";
    echo "Частота отказов: " . ($backend['stats']['failureRate'] * 100) . "%\n\n";
}
```

### Отслеживание захваченных блокировок

[](#отслеживание-захваченных-блокировок)

```
// Узнать, какие блокировки захвачены и какими бэкендами
$locks = $mutex->getAcquiredLocks();

foreach ($locks as $name => $backendIndex) {
    echo "Блокировка '$name' захвачена бэкендом #{$backendIndex}\n";
}
```

Расширенное использование
-------------------------

[](#расширенное-использование)

### Ручное управление Circuit Breakers

[](#ручное-управление-circuit-breakers)

```
// Принудительно открыть circuit breaker бэкенда (для тестирования)
$mutex->forceBackendOpen(0);

// Принудительно закрыть circuit breaker бэкенда
$mutex->forceBackendClose(0);

// Сбросить все circuit breakers
$mutex->resetCircuitBreakers();
```

### Алертинг при сбоях

[](#алертинг-при-сбоях)

```
use beeline\ResilientMutex\ResilientMutex;

class MonitoredMutex extends ResilientMutex
{
    public function acquire($name, $timeout = 0): bool
    {
        $result = parent::acquire($name, $timeout);

        // Проверяем состояние бэкендов
        $status = $this->getBackendStatus();

        foreach ($status as $backend) {
            if ($backend['state'] === 'open') {
                // Отправляем алерт
                $this->sendAlert("Бэкенд {$backend['class']} недоступен!");
            }
        }

        return $result;
    }

    private function sendAlert(string $message): void
    {
        // Интеграция с вашей системой мониторинга
        Yii::error($message, __METHOD__);
    }
}
```

Рекомендуемые конфигурации
--------------------------

[](#рекомендуемые-конфигурации)

### Высокая доступность (Redis + PostgreSQL)

[](#высокая-доступность-redis--postgresql)

```
'backends' => [
    // Быстрый Redis для нормальной работы
    [
        'mutex' => ['class' => RedisMutex::class, 'redis' => 'redis'],
        'retries' => 3,
        'retryDelay' => 50,
        'circuitBreaker' => [
            'failureThreshold' => 0.5,
            'windowSize' => 20,
            'timeout' => 30,
        ],
    ],
    // Надёжный PostgreSQL как резерв
    [
        'mutex' => ['class' => PgsqlMutex::class, 'db' => 'db'],
        'retries' => 2,
        'retryDelay' => 100,
        'circuitBreaker' => [
            'failureThreshold' => 0.7,
            'windowSize' => 10,
            'timeout' => 60,
        ],
    ],
],
```

### Максимальная отказоустойчивость (три бэкенда)

[](#максимальная-отказоустойчивость-три-бэкенда)

```
'backends' => [
    // Redis
    [
        'mutex' => ['class' => RedisMutex::class, 'redis' => 'redis'],
        'retries' => 2,
        'retryDelay' => 50,
    ],
    // PostgreSQL Advisory Locks
    [
        'mutex' => [
            'class' => \beeline\PgsqlAdvisoryMutex\PgsqlAdvisoryMutex::class,
            'db' => 'db',
        ],
        'retries' => 2,
        'retryDelay' => 75,
    ],
    // Файловые блокировки (последний резерв)
    [
        'mutex' => [
            'class' => \yii\mutex\FileMutex::class,
            'mutexPath' => '@runtime/mutex',
        ],
        'retries' => 1,
        'retryDelay' => 100,
    ],
],
```

### Быстрый failover (Redis + File)

[](#быстрый-failover-redis--file)

```
'backends' => [
    [
        'mutex' => ['class' => RedisMutex::class, 'redis' => 'redis'],
        'retries' => 1,  // Одна попытка
        'retryDelay' => 10,  // Быстрый переход
        'circuitBreaker' => [
            'failureThreshold' => 0.3,  // Быстрое открытие
            'timeout' => 10,  // Быстрое восстановление
        ],
    ],
    [
        'mutex' => ['class' => FileMutex::class],
        'retries' => 1,
        'retryDelay' => 0,
    ],
],
'retryStrategy' => ResilientMutex::RETRY_GLOBAL,
'globalRetries' => 3,
```

Примеры использования
---------------------

[](#примеры-использования)

### Обработка критических задач

[](#обработка-критических-задач)

```
use Yii;

class CriticalTaskProcessor
{
    public function processTask(int $taskId): void
    {
        $mutex = Yii::$app->mutex;
        $lockName = "task:{$taskId}";

        if (!$mutex->acquire($lockName, 10)) {
            throw new \RuntimeException("Не удалось захватить блокировку для задачи {$taskId}");
        }

        try {
            // Обработка задачи
            $this->performProcessing($taskId);

            // Проверяем, не было ли проблем с бэкендами
            $status = $mutex->getBackendStatus();
            $primaryState = $status[0]['state'] ?? 'unknown';

            if ($primaryState !== 'closed') {
                Yii::warning("Задача {$taskId} обработана, но основной mutex бэкенд в состоянии: {$primaryState}");
            }
        } finally {
            $mutex->release($lockName);
        }
    }
}
```

### Координация микросервисов

[](#координация-микросервисов)

```
use beeline\ResilientMutex\ResilientMutex;

class DistributedService
{
    private ResilientMutex $mutex;

    public function __construct()
    {
        $this->mutex = new ResilientMutex([
            'backends' => [
                [
                    'mutex' => ['class' => RedisMutex::class, 'redis' => 'redis'],
                    'retries' => 3,
                ],
                [
                    'mutex' => ['class' => PgsqlMutex::class, 'db' => 'db'],
                    'retries' => 2,
                ],
            ],
        ]);
    }

    public function synchronizeOperation(string $operationId): mixed
    {
        $lockName = "operation:{$operationId}";

        if ($this->mutex->acquire($lockName, 30)) {
            try {
                return $this->executeOperation($operationId);
            } finally {
                $this->mutex->release($lockName);
            }
        }

        throw new \RuntimeException('Операция уже выполняется другим сервисом');
    }

    public function getSystemHealth(): array
    {
        return [
            'mutex_backends' => $this->mutex->getBackendStatus(),
            'acquired_locks' => count($this->mutex->getAcquiredLocks()),
        ];
    }
}
```

Диаграмма работы
----------------

[](#диаграмма-работы)

```
Запрос блокировки
       ↓
┌──────────────────┐
│ Бэкенд 1 (Redis) │
└──────────────────┘
       ↓
   Успех? ──→ Да ──→ Возврат блокировки
       ↓
      Нет
       ↓
Circuit Breaker открыт? ──→ Да ──→ Пропуск бэкенда
       ↓
      Нет
       ↓
Повтор N раз
       ↓
   Неудача
       ↓
┌─────────────────────────┐
│ Бэкенд 2 (PostgreSQL)   │
└─────────────────────────┘
       ↓
   Успех? ──→ Да ──→ Возврат блокировки
       ↓
      Нет
       ↓
Повтор N раз
       ↓
   Неудача
       ↓
Возврат false

```

Тестирование
------------

[](#тестирование)

```
# Запуск тестов
vendor/bin/phpunit

# Запуск с покрытием
vendor/bin/phpunit --coverage-html coverage/
```

Производительность
------------------

[](#производительность)

### Накладные расходы

[](#накладные-расходы)

- **Circuit Breaker проверка**: ~0.01мс
- **Переключение между бэкендами**: ~0.1-1мс (зависит от бэкенда)
- **Память**: ~1KB на бэкенд для circuit breaker

### Рекомендации

[](#рекомендации)

1. **Используйте быстрые бэкенды первыми**: Redis → PostgreSQL → File
2. **Настраивайте агрессивные circuit breakers для ненадёжных бэкендов**
3. **Мониторьте состояние бэкендов** через `getBackendStatus()`
4. **Используйте RETRY\_PER\_BACKEND для критичных операций**
5. **Используйте RETRY\_GLOBAL для быстрого failover**

Отладка
-------

[](#отладка)

### Включение подробного логирования

[](#включение-подробного-логирования)

```
'mutex' => [
    'class' => ResilientMutex::class,
    'backends' => [...],
    'on beforeAcquire' => function ($event) {
        Yii::debug("Попытка захвата блокировки: {$event->name}");
    },
    'on afterAcquire' => function ($event) {
        Yii::info("Блокировка захвачена: {$event->name} на бэкенде {$event->backend}");
    },
    'on backendFailure' => function ($event) {
        Yii::warning("Бэкенд {$event->backend} отказал: {$event->error}");
    },
],
```

### Мониторинг в production

[](#мониторинг-в-production)

```
// Периодически проверяйте состояние
$status = $mutex->getBackendStatus();

foreach ($status as $backend) {
    // Отправляйте метрики в систему мониторинга
    $metrics->gauge('mutex.backend.failure_rate', $backend['stats']['failureRate'], [
        'backend' => $backend['class'],
        'index' => $backend['index'],
    ]);

    if ($backend['state'] === 'open') {
        $metrics->increment('mutex.backend.circuit_open', [
            'backend' => $backend['class'],
        ]);
    }
}
```

Лицензия
--------

[](#лицензия)

GNU Lesser General Public License 3.0

###  Health Score

35

—

LowBetter than 79% of packages

Maintenance68

Regular maintenance activity

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

6

Last Release

186d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/76ddc43524bb32eb36568e25b6ae283bc25bb51a4572789997909092145af0f5?d=identicon)[pozitronik](/maintainers/pozitronik)

---

Top Contributors

[![pozitronik](https://avatars.githubusercontent.com/u/2357892?v=4)](https://github.com/pozitronik "pozitronik (12 commits)")

---

Tags

mutexyii2high availabilitycircuit breakerfault toleranceresilience

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/beeline-yii2-resilient-mutex/health.svg)

```
[![Health](https://phpackages.com/badges/beeline-yii2-resilient-mutex/health.svg)](https://phpackages.com/packages/beeline-yii2-resilient-mutex)
```

###  Alternatives

[gabrielanhaia/laravel-circuit-breaker

Laravel integration for PHP Circuit Breaker — multiple storage drivers, middleware, Artisan commands, and event system

481.0k](/packages/gabrielanhaia-laravel-circuit-breaker)[dmstr/yii2-cookie-consent

Yii2 Cookie Consent Widget

1452.6k](/packages/dmstr-yii2-cookie-consent)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
