1

我刚刚接受了一个类似的问题(PHP + MySQL Queue),但我意识到这不是我的问题的正确问题,而是我的问题的正确答案:)

我有一个 MySQL(MyISAM 类型)的站点表,供工作人员抓取。

CREATE TABLE `site` (
  `id` int(11) NOT NULL auto_increment,
  `url` text,
  `last_pop` int(13) default NULL,
  `md5` varchar(32) default NULL,
  `disabled` tinyint(1) default '0',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `md5` (`md5`),
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

我需要的是不重复地为每个工人报废一个站点。所以,如果我有 3 个站点和 2 个工作人员,系统需要像这样工作:

      ID URL   LAST_POP
t4    1  site1 t1         <- worker1 scrap site1
t4    2  site2 t2         <- worker2 scrap site2
t5    3  site3 t3         <- worker1 scrap site3
t6    1  site2 t4         <- worker2 scrap site2
t6    2  site1 t4         <- worker1 scrap site1
t7    3  site3 t5         <- worker2 scrap site3
....

这就像 last_pop ASC 的循环队列排序器。

我怎样才能做到这一点?

4

2 回答 2

1

您可能希望跟踪每个站点的两条信息:上次抓取的时间以及当前是否正在抓取。

使用其他问题的答案,将该scraping字段设置为工作人员的 id 以将其与其他工作人员锁定。当工作人员完成任务后,将scraping字段设置为当前时间null,并将last_scrape日期设置为当前时间。

CREATE TABLE `site` (
  `id` int(11) NOT NULL auto_increment,
  `url` text,
  `last_scrape` TIMESTAMP,
  `scraping` tinyint(1) default NULL,
  `md5` varchar(32) default NULL,
  `disabled` tinyint(1) default '0',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `md5` (`md5`),
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

锁定并检索下一个作业(上次抓取时间最长的站点):

Update site
  set `scraping` = '$worker_id' 
  where `scraping` is null 
  order by `last_scrape` ASC limit 1;

$job = 
  Select * from site
  where `scraping` = '$worker_id'

将作业释放回队列:

Update site
  set `scraping` = NULL,
  `last_scrape` = NOW()
  where `scraping` = '$worker_id';
于 2009-11-07T00:14:04.270 回答
0

为什么不添加一个额外的布尔列 STATUS 以便您可以按 LAST_POP 排序。因此,当工作人员选择一个站点进行报废时,使用UPDATE site SET status = '1'. 当下一个工作人员选择下一个站点时,使用SELECT * FROM site WHERE status = '0' ORDER BY last_pop ASC.

于 2009-11-07T00:09:10.860 回答