Как предотвратить состояние гонки в node.js? - PullRequest
0 голосов
/ 19 сентября 2018

Может кто-нибудь объяснить мне, как предотвратить условия гонки в node.js с помощью Express?

Если есть, например, два метода:

router.get('/addUser/:department', function(req, res) { ...})

router.get('/deleteUser/:department', function(req, res) { ...})

Обе функции используют неблокирующую IОперация / O (например, запись в файл или базу данных).

Теперь кто-то вызывает addUser с отделом «A», а кто-то пытается удалить всех пользователей с отделом «A».Как я могу решить эту (или другие подобные) условия гонки?

  1. Как решить проблему, если у каждого пользователя есть свой файл / база данных?

  2. Как решить проблему, если яу меня есть один файл пользователя (файловая система), который мне нужно прочитать, изменить и записать снова?

Примечание. Это просто пример для понимания.Здесь не нужны подсказки по оптимизации.

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Чтобы заархивировать эту цель, вам нужно реализовать связь в двух сервисах.

Это можно сделать с помощью простой очереди операций для обработки каждого запроса по порядку.Эффект контраргумента заключается в том, что запрос, ожидающий очередь, будет иметь задержанный ответ (и может произойти тайм-аут).

Простая реализация "мета":

const operationQueue = new Map();

const eventEmitter = new events.EventEmitter();

router.get('/addUser/:department', function(req, res) {
    const customEvent = `addUser-${new Date().getTime()}`;
    const done = () => { 
        res.send('done'); 
        operationQueue.delete(customEvent);
    };
    eventEmitter.once(customEvent, done);
    operationQueue.set(customEvent, () => addUser(customEvent, req));
})

router.get('/deleteUser/:department', function(req, res) {
    const customEvent = `deleteUser-${new Date().getTime()}`;
    const done = () => { 
        res.send('done'); 
        operationQueue.delete(customEvent);
    };
    eventEmitter.once(customEvent, done);
    operationQueue.set(customEvent, () => deleteUser(customEvent, req));
})

function addUser(customEvent, req){
    // do the logic
    eventEmitter.emit(customEvent, {done: true});
}

function deleteUser(customEvent, req){
    // do the logic
    eventEmitter.emit(customEvent, {done: true});
}

// not the best performance
setInterval(()=>{
    const process = operationQueue.shift();
    if(process) {
        process();
    }
}, 1);

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

0 голосов
/ 19 сентября 2018

(Это очень широкий вопрос.)

Как правило, можно использовать базу данных (вместо обычных текстовых файлов) и использовать встроенные механизмы блокировки.

Примермеханизмы блокировки в системе управления базами данных Postgres: https://www.postgresql.org/docs/10/static/explicit-locking.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...