使用socket.io进行排队

时间:2011-11-26 22:20:04

标签: javascript mysql node.js message-queue socket.io

我使用node.js每10秒查询一次MySQL数据库表。使用socket.io,在每10秒进行一次数据库查询后,每个连接的浏览器将从该查询中收到一组唯一的行。

问题:按照我实现此方式的方式,每隔10秒钟,有多个浏览器可能会收到相同的行集。我使用了一些检出系统(如下所示)来标记已经发送到另一个浏览器的行,但它似乎并不是一直有效。如何保证每个浏览器每次都获得一组唯一的行?

换句话说,其他浏览器同时查询数据库比锁定行更快!

实施

每10秒发生以下情况

  1. Node.js app查询MySQL数据库表SELECT * FROM table WHERE checkout = 0
  2. 如果返回结果,则node.js服务器io.sockets.send向所有连接的浏览器发送消息,说明行可用
  3. 所有已连接的客户端都使用socket.emit('ready')
  4. 进行回复
  5. 服务器收到ready emit,再次查询数据库以选择3行,然后更新表以将这3行的checkout列设置为1
  6. Server然后将数据库查询结果发送到客户端
  7. 显然,第二个浏览器导致SELECT...查询的时间比第一个浏览器用checkout = 1更新行的时间要短。还有另一种方法可以排队吗?

    截图

    正如您在2个浏览器同时打开的屏幕截图中所看到的,通常两个浏览器都会获得相同的行集。如图所示,行的ID为console.logenter 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 :(得分:0)

简单的解决方案(如果性能不是一个大问题)是一个锁定你触摸的每一行以便阅读的事务 - 如果其他人试图在你的选择和插入之间读取,那么他们将不得不等到你的锁被释放< / p>

答案 1 :(得分:0)

在选择行之前更新行。例如

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

uniqueNumber可以是进程/线程ID,浏览器客户端ID,或者在node.js环境中适合的东西(我不熟悉它)。现在选择具有该唯一job_checkout的行。