简体   繁体   English

使用socket.io排队

[英]Queuing using socket.io

I am using node.js to query a MySQL database table every 10 seconds. 我正在使用node.js每10秒查询一次MySQL数据库表。 Using socket.io, after the database query every 10 secs, every connected browser will receive a unique batch of rows from that query. 使用socket.io,每隔10秒查询一次数据库后,每个连接的浏览器将从该查询中接收到唯一的一行行。

Problem: With the way I implemented this, at every 10 second interval, there is a chance that more than 1 browsers receive the same set of rows. 问题:使用我实施此方法的方式,每隔10秒就有一个以上的浏览器接收相同的行集。 I used some checking out system (as shown below) to mark rows that have been sent to another browser already, but it does not seem to work all the time. 我使用了一些检出系统(如下所示)来标记已经发送到另一个浏览器的行,但是它似乎并不能一直工作。 How can I guarantee that each browser gets a unique set of rows each time? 如何保证每个浏览器每次都获得唯一的行集?

In other words, the simultaneous querying of the db by the other browsers are faster than the locking of the rows! 换句话说,其他浏览器同时查询数据库比锁定行要快!

Implementation 实作

Every 10 seconds, the following occurs 每隔10秒就会发生以下情况

  1. Node.js app querys the MySQL database table SELECT * FROM table WHERE checkout = 0 Node.js应用程序查询MySQL数据库表SELECT * FROM table WHERE checkout = 0
  2. If result is returned, node.js server io.sockets.send a message to all connected browser saying that rows are available 如果返回结果,则node.js服务器io.sockets.send向所有连接的浏览器io.sockets.send一条消息,指出行可用
  3. All connected clients respond with a socket.emit('ready') 所有连接的客户端socket.emit('ready')响应
  4. Server receives the ready emit, querys the database again to select 3 rows, then update tables to set the checkout column of these 3 rows to be 1 服务器接收到ready发射,再次查询数据库以选择3行,然后更新表以将这3行的checkout列设置为1
  5. Server then emits the database query result to the client 然后,服务器将数据库查询结果发送给客户端

Apparently it seems that it takes lesser time for the 2nd browser to cause a SELECT... query than for the first browser to update the rows with checkout = 1 . 显然,与第一个浏览器使用checkout = 1更新行相比,第二个浏览器引发SELECT...查询的时间似乎更少。 Is there another way to do this queueing? 还有另一种方法可以进行此排队吗?

Screenshot 屏幕截图

As you can see in the screenshot of 2 browsers open at the same time, often both browsers will get the same set of rows. 正如您在同时打开两个浏览器的屏幕快照中看到的那样,通常两个浏览器都将获得相同的行集。 The ids of the rows are console.log ed as shown. 如图所示,这些行的id是console.log 在此处输入图片说明

CODE

Node.js 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 ]);
}

一种简单的解决方案(如果性能不是大问题)是一种事务,它锁定您触摸要读取的每一行-如果其他任何人试图在您的选择和插入之间进行读取,那么他们将不得不等到您的锁定被释放为止

update the rows before selecting them. 在选择行之前更新它们。 eg 例如

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

uniqueNumber could be a process/thread id, or browser client id, or something suitable in the node.js environment(I'm not familiar with it). uniqueNumber可以是进程/线程ID,也可以是浏览器客户端ID,也可以是在node.js环境中适合的东西(我不熟悉)。 Now select the rows with that unique job_checkout. 现在,选择具有唯一job_checkout的行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM