Вопросы по работе метода acquire в Mutex Yii2

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Аватара пользователя
MarkL
Сообщения: 68
Зарегистрирован: 2017.07.05, 20:37

Вопросы по работе метода acquire в Mutex Yii2

Сообщение MarkL »

Есть вопросы к логике работы Mutex Yii2;
Допустим, есть Mutex:

Код: Выделить всё

$mutex = new FileMutex();
$mutexName = 'order-mutex';
$unlockSeconds = 5;

if ($mutex->acquire($mutexName, $unlockSeconds)) {
  // код
  $mutex->release($mutexName);
} else {
  throw new \Exception('');
}
Вопросы:
1. Что значит второй параметр $timeout в методе acquire($name, $timeout = 0)? Это выставление таймаута, прежде чем будет обрабатываться следующий запрос?
$timeout time (in seconds) to wait for lock to be released. Defaults to zero meaning that method will return false immediately in case lock was already acquired.
Из PHPDoc
2. При каких условиях метод acquire() возвращает false, из-за чего выходит бросается исключение?
С этим связана основная проблема: при обращении к API, некоторые клиенты получают данное исключение, вместо постановки(так ли?) запроса в очередь.
Аватара пользователя
MarkL
Сообщения: 68
Зарегистрирован: 2017.07.05, 20:37

Re: Вопросы по работе метода acquire в Mutex Yii2

Сообщение MarkL »

Благодаря ответу skynin в теме Какая логика работы таймаута в Mutex? стало более понятна работа метода.
Получается, если в очереди есть запрос, метод acquire() возвращает false?


------------------------------------------------------------------------------------------------------------

UPD: Нашел тему, где на примере описали как это работает: Проверка существования mutex lock.

Выходит:
1. $timeout служит для того, чтобы подождать N времени, пока процесс "отпустит" блокировку. Если таймаут вышел - возвращается false.
2. acquire() возвращается false, если есть блокировка с именем, которое передается первым аргументом.

Если да, остаётся вопрос: для некоторых клиентов API очень желательно, чтобы до исключения не доходило.
В боевой практике Mutex'ы использую для заказов, чтобы избежать последствия состоянии гонки Mutex с именем: "order".
Выходит, для удоволетворения моего запроса можно создать Mutex: "order_%userId%", где %userId% имя пользователя и под каждого сделать свою очередь, и сделать побольше время timeout'а acquire(), скажем, 30 секунд?
skynin
Сообщения: 400
Зарегистрирован: 2017.12.12, 10:09

Re: Вопросы по работе метода acquire в Mutex Yii2

Сообщение skynin »

MarkL писал(а): 2019.11.28, 19:55 Выходит, для удоволетворения моего запроса можно создать Mutex: "order_%userId%", где %userId% имя пользователя и под каждого сделать свою очередь, и сделать побольше время timeout'а acquire(), скажем, 30 секунд?
да, так и делается - имя мьютекса с каким-то id
отдельную очередь - не очень понятно зачем, о чем речь

в идеале же, если нам нужно залочить не бизнес операцию(не имеющую прямого, простого отображения на персистентные данные), а данные, то предпочтительнее использовать средства БД
у MySQL - https://dev.mysql.com/doc/refman/8.0/en ... reads.html
SELECT ... FOR SHARE
SELECT ... FOR UPDATE

аналогичные есть во всех БД

Для удобства работы расширить ActiveQuery в стиле https://github.com/skynin/mysql-activequery

БД более тонко, гранулировано решит задачу необходимых блокировок
Не желайте странного, и не будет у вас головной боли чтобы достичь этого странного.
Тем более что окажется что оно вам и не нужно было, странное это.
Ответить