Как исправить состояние гонки в узле js + redis + mongodb web application - PullRequest
0 голосов
/ 02 апреля 2019

Я создаю веб-приложение, которое будет обрабатывать много транзакций в секунду.Я использую Express Server с Node Js.Что касается базы данных, я использую Redis для хранения атрибутов пользователя, которые будут постоянно колебаться в зависимости от цены акций.Я использую MongoDB для хранения полупостоянных атрибутов, таких как конфигурация заказа, конфигурация пользователя и т. Д.,

Я попал в состояние гонки, когда несколько заказов, размещенных пользователем, обрабатываются одновременно, но только одинбыло бы приемлемо в качестве проверки атрибута Redis, который хранит поле, не позволил бы обе транзакции.

Другая проблема заключается в том, что моя логика приложения чередует вызовы чтения и записи Redis и MongoDB.Итак, как бы я решил проблему состояния гонки для обеих БД

. Я думаю о том, чтобы попытаться СМОТРЕТЬ и MULTI + EXEC на Redis, чтобы убедиться, что для данного пользователя одновременно выполняется только одна транзакция.Или я могу настроить очередь на узле / Redis, которая будет обрабатывать заказы один за другим.Я не уверен, какой подход правильный.Или как его реализовать.

Это все псевдокод.Логика приложения намного сложнее с несколькими условиями.Я чувствую, что вся моя логика приложения является критическим разделом (что я считаю плохим)


//The server receives a request from Client to place an Order
getAvailableMargin(user.username).then((margin) => { // REDIS call to fetch margin of user. This fluctuates a lot, so I store it in REDIS
            if (margin > 0) {
                const o = {  // Prepare an order
                    user: user.username,
                    price: orderPrice,
                    symbol: symbol
                }

                const order = new Order(o);
                order.save((err, o) => { // Create new Order in MongoDB
                        if (err) {
                            return next(err);
                        }
                        User.findByIdAndUpdate(user._id, {
                            $inc: {
                                balance: pl
                            }
                        }) // Update balance in MongoDB
                        decreaseMargin(user.username) //  decrease margin of User in REDIS
                    );

                }

            });



Считайте, что маржа равна 1, и с каждым новым маржемным запасом уменьшается на 1.

Теперьесли два запроса получены одновременно, то в Redis маржа будет равна 1 для обоих запросов, что приведет к состоянию гонки.Кроме того, теперь в MongoDB будут открыты два ордера.Когда на самом деле в конце первого ордера маржа должна была стать 0, а второй ордер должен был быть отклонен.Другая проблема заключается в том, что мы теперь продвинулись и обновили баланс для Пользователя в MongoDB дважды, по одному на каждый ордер.

Ожидается, что один из ордеров не должен быть выполнен, и следует повторить попытку, проверивновое поле в Redis.И баланс пользователя также должен был обновляться только один раз.

По сути, мне нужно было бы реализовать наблюдение на Redis и MongoDB и каким-либо образом повторить транзакцию, если какие-либо из наблюдаемых полей / документов изменятся?Это вообще возможно?Или есть гораздо более простое решение, которое я мог бы упустить?

...