Redis & Java в многопоточном приложении поможет! - PullRequest
1 голос
/ 28 февраля 2011

У нас есть приложение, которое в настоящее время имеет потоки (около 50 потоков) для обработки транзакций.

Мы настроили базу данных Redis и используем DECRBY для удержания кредитов из учетной записи пользователя.

Вот пример процесса:

1. Get amount of credits for this transaction
2. Get current credit amount from from Redis: GET <key>
3. If amount of credits exceeds amount cost of transaction continue
4. DECRBY the transaction amount from Redis.

Проблема, с которой я столкнулся, очевидна: когда количество кредитов пользователей достигает 0, транзакция не выполняется (хорошо), но она пропускает около 10-20 транзакций из-за многопоточности.

Я думал о настройке WATCH, MULTI, EXEC с Redis, а затем повторите попытку, но не приведет ли это к узкому месту (я думаю, это называется условиями гонки), потому что потоки будут постоянно бороться за завершение транзакции.

Есть предложения?

Ответы [ 3 ]

2 голосов
/ 14 мая 2011

Блокировка - это то, что вам нужно. Поскольку блокировки БД дороги, вы можете реализовать простую схему блокировки в Redis с помощью SETNX, а также избежать условий гонки. Это хорошо объяснено здесь - http://redis.io/commands/setnx. Но вам все еще нужно реализовать повторы на уровне приложения.

0 голосов
/ 26 января 2017

Вы можете попытаться использовать реализацию объекта блокировки на основе Redis для Java, предоставляемую Redisson framework вместо повторения попыток с помощью команд WATCH-MULTI. Работа с WATCH-MULTI включает в себя ненужные запросы к Redis при каждой попытке, которая работает намного медленнее, чем уже полученная блокировка.

Вот пример кода:

Lock lock = redisson.getLock("transationLock");
lock.lock();
try {
  ... // instructions
} finally {
   lock.unlock();
}
0 голосов
/ 28 февраля 2011

Это не самый обычный способ сделать это IMO (самый обычный способ, вероятно, это использовать блокировку в СУБД), но использование WATCH, MULTI, EXEC выглядит как CAS и некажется мне слишком странным

Я бы предположил, что автор Redis намеревался использовать WATCH таким образом.Очевидно, что производительность зависит от того, как эта вещь реализована (чего я не знаю), но я держу пари, что она будет работать довольно хорошо.

Это потому, что, вероятно, будет очень мало или почти нет конкуренции за одни и те же ключи в вашей ситуации (какова вероятность того, что пользователь лихорадочно выдаст транзакции для себя)?для первой операции своп будет действительно хорошо.Поэтому повторная попытка произойдет только в очень редких случаях.Поскольку Redis кажется заслуживающей доверия платформой, они также, вероятно, знают, что делают (т.е. меньше споров = легкая работа для Redis, поэтому он, вероятно, справится с этим!).

...