Комментарии 2
Отличная статья! Очень наглядно разобрана классическая проблема в распределённых системах: когда пытаются эмулировать блокировки через SELECT + INSERT + SELECT FOR UPDATE. Бесспорно, это решает проблему, но на проде такие подходы часто дают непредсказуемые задержки и усложняют отладку из‑за блокировок строк и долгих транзакций.
По сути здесь решается классическая задача распределённого захвата ресурса (Claim/Lock) без дублирования сущностей. В in‑memory хранилищах с нативными атомиками (например, в HurriCache) подобные сценарии для реализации стейт‑машин (конечных автоматов) решаются проще и без тяжёлой артиллерии вроде транзакций БД и частичных индексов.
Самый простой способ — использовать атомарный compareAndSet. Это будет выглядеть примерно вот так (Java):
java
// Пример: ожидаем состояние 0 (IDLE), если оно там есть — атомарно ставим 1 (REGISTERING)
//orderId это ключ который отвечать за идентификатор платежа он был создан ранее
hurricacheClient.compareAndSet(orderId, 0L, 1L)
.thenCompose(casRes -> {
if (casRes.getSuccess()) {
// Успех! Мы единственные захватили право на старт.
// Теперь можно спокойно идти во внешний API (I/O),
// никто через CAS не сможет изменить состояние
return executeGatewayCallAsync(orderId);
} else {
// Конкурентный поток уже обрабатывает заказ
//-> возвращаем ошибку
return CompletableFuture.completedFuture(false);
}
});При высокой нагрузке такой подход даёт низкие задержки, потому что CAS работает в памяти без сетевой транзакции. CAS и атомарные операции поддерживаются HurriCache нативно и поддержаны на уровне процессора
Если интересны детали - обращайтесь. Данные в профиле
Интересная статья, хотя мне чутка тяжеловато было понять некоторые момент, но для чуваков с опытом в данном вопросе я думаю будет достаточно полезно, рекомендую👍

Два клика — одна оплата: Форсаж вокруг платежного шлюза