Реалізація Lock’ів на сайтах Alawar
Сьогодні ми поговоримо про блокування та покажемо свою реалізацію. Кожен із розробників неодноразово стикався з проблемою, коли необхідно забезпечити однопоточне використання будь-якого ресурсу.
Часто задля забезпечення такого блокування використовується схема зі створенням спеціального файла, наявність якого визначає факт зайнятості тієї чи іншої ресурсу.
Такий підхід досить простий у реалізації, але має низку недоліків. Серед недоліків можна назвати:
- відсутність 100% гарантії блокування за великої кількості потоків;
- блокування працює у межах одного сервера;
- і найнеприємніше - якщо процес, який поставив блокування чомусь його не зняв, то інші процеси так і не зможуть отримати доступ до цього ресурсу, поки вручну або якимось іншим способом це блокування не буде знято.
Коли потрібно блокування?
Як зробити самому?
Щоб реалізувати правильні блокування, потрібно розуміти принципи атомарності та транзакційності. Їх ми описувати цієї статті нічого очікувати, т.к. В Інтернеті є вже багато інформації на ці теми.
При реалізації ми визначили основні операції під час роботи з блокуваннями:
- взяти блокування на певний час
- зняти блокування через заданий час
- продовжити блокування
- відпрацювати кейс коли блокування було перехоплено
Нам був ближчий Redis, тому ми реалізували свій механізм блокувань, який не має недоліків перерахованих вище, на Redis-і.
Як зроблено блокування у нас
Наша реалізація використовується в проекті нафреймворке Yii та використовує для підключення до Redis через бібліотеку Rediska. Але зав'язка на Yii, як і Rediska, невелика, тому цей код можна буде використовувати в будь-якому проекті на PHP.
Отже, приступимо до найцікавішого:
Базовий клас блокування
Клас RedisLock
У цьому класі блокування здійснюються з використанням Redis:
Приклад використання
Допустимо, у нас є скрипт, який формує звіти. І це скрипт немає сенсу запускати одночасно у кілька потоків, т.к. вони всі в результаті видадуть той самий результат, але кожен вимагатиме в ході роботи велику кількість ресурсів. Ми знаємо, що цей скрипт загалом відпрацьовує за 40-50 хвилин, тому зробимо невеликий запас і поставимо блокування на 60 хвилин.
Сподіваємося, що наша реалізація буде вам корисною.