Очередь с использованием socket.io - PullRequest
1 голос
/ 27 ноября 2011

Я использую node.js для запроса таблицы базы данных MySQL каждые 10 секунд. Используя socket.io, после запроса к базе данных каждые 10 секунд каждый подключенный браузер получит уникальный пакет строк из этого запроса.

Проблема: Благодаря тому, как я это реализовал, каждые 10 секунд существует вероятность того, что более 1 браузера получат один и тот же набор строк. Я использовал некоторую систему проверки (как показано ниже), чтобы отметить строки, которые уже были отправлены в другой браузер, но, похоже, не работает все время. Как я могу гарантировать, что каждый браузер каждый раз получает уникальный набор строк?

Другими словами, одновременный запрос базы данных другими браузерами быстрее, чем блокировка строк!

Осуществление

Каждые 10 секунд происходит следующее

  1. Приложение Node.js запрашивает таблицу базы данных MySQL SELECT * FROM table WHERE checkout = 0
  2. Если результат возвращается, сервер node.js io.sockets.send - сообщение для всех подключенных браузеров о том, что строки доступны
  3. Все подключенные клиенты отвечают socket.emit('ready')
  4. Сервер получает emit ready, снова запрашивает базу данных, чтобы выбрать 3 строки, затем обновляет таблицы, чтобы задать для столбца checkout этих 3 строк значение 1
  5. Затем сервер отправляет клиенту результат запроса базы данных

По-видимому, для второго браузера требуется меньше времени, чтобы вызвать запрос SELECT..., чем для первого браузера, чтобы обновить строки с checkout = 1. Есть ли другой способ сделать эту очередь?

Скриншот

Как вы можете видеть на скриншоте двух открытых одновременно браузеров, часто оба браузера получают одинаковый набор строк. Идентификаторы строк console.log редактируются, как показано. enter image description here

CODE

Node.js

io.sockets.on('connection', function(socket) {
    // Client ready to take jobs after receiving broadcast
    socket.on('ready', function() {
        getListings(function(listings) {
            socket.emit('job', listings);   // send jobs
        });
    });

});

var getListings = function(callback) {
    client.query('SELECT * FROM table ' + 
                'WHERE job_checkout = 0 ' +
                'ORDER BY listing_id ASC ' +
                'LIMIT 0, 3', 
                function(error ,results, fields) {
                    if (error) 
                        throw error;
                    // Checkout listing now!
                    checkoutListings(results);
                    callback(results);
                });
};

var checkoutListings = function(listings) {
    for (var i = 0; i < listings.length; i++) {
        checkoutListing(listings[i]);
    }
}

var checkoutListing = function(listing) {
    client.query('UPDATE table ' + 
                    'SET job_checkout = 1 ' +
                    'WHERE listing_id = ?',
                    [ listing.listing_id ]);
}

Ответы [ 2 ]

0 голосов
/ 27 ноября 2011

обновить строки перед их выбором.например,

update table 
set job_checkout = uniqueNumber 
where job_checkout = 0
limit 10

uniqueNumber может быть идентификатором процесса / потока, идентификатором клиента браузера или чем-то подходящим в среде node.js (я не знаком с этим).Теперь выберите строки с этим уникальным job_checkout.

0 голосов
/ 27 ноября 2011

Простое решение (если производительность не является большой проблемой) - это транзакция, которая блокирует каждую строку, к которой вы прикоснулись, для чтения - если кто-то попытается прочитать между вашим выбором и вставкой, ему придется ждать, пока ваша блокировка не будет снята

...