Python 如何并行:6台机器,800万独立文档在数据库中进行处理
背景: 我在数据库中有800万个独立文档要处理。文档之间没有依赖关系,这意味着流程可以并行化。处理一个文档后,结果将保存回数据库 有6台机器供我使用 当前解决方案 在MySQL中使用一个表存储文档 现在,我将这些行平均划分为6个共享,每个共享由一台机器处理 当前解决方案的缺点 某些分区可能需要更长的时间来处理,从而使某些计算机在其他计算机空闲时处于忙碌状态 要求Python 如何并行:6台机器,800万独立文档在数据库中进行处理,python,mysql,parallel-processing,Python,Mysql,Parallel Processing,背景: 我在数据库中有800万个独立文档要处理。文档之间没有依赖关系,这意味着流程可以并行化。处理一个文档后,结果将保存回数据库 有6台机器供我使用 当前解决方案 在MySQL中使用一个表存储文档 现在,我将这些行平均划分为6个共享,每个共享由一台机器处理 当前解决方案的缺点 某些分区可能需要更长的时间来处理,从而使某些计算机在其他计算机空闲时处于忙碌状态 要求 我想找到一种有效地平衡任务负载的方法/框架 我使用Python作为数据处理工具,希望有适合Python的工具 您不应该将行划分为相等的
您不应该将行划分为相等的共享,而应该向文档表中添加一个进度字段(您应该真正创建一个进度表并进行外部联接,但您会明白这一点)。然后在每个worker中,您首先预订一组文档(假设
id
是主键,WORKERID
是每个worker的唯一id):
(如果您使用的是旧版本的MySQL,则可能需要更复杂的语法:)
确保您的限制足够大,以便数据库有喘息的空间,但不要太大,以至于您必须等待最后一个工作人员完成他的第10000个文档:-)
然后可以开始迭代:
c.execute("select * from documents where progress = %s", my_worker_id)
for doc in c.fetchall():
# process doc..
c.execute("update documents set progress = 'done' where id = %s", doc.id)
cn.commit()
这样做的优点是非常容易实现,速度非常快,并且可以重新启动任何工作程序等
如果你只有6个工人,我就用手启动他们
哦,您可以使用简单的sql语句手动监视进度:
select progress, count(*)
from documents
group by progress
order by progress
这将告诉您还有多少剩余(progress=null)、多少已完成(progress='done')以及每个工人队列中有多少人(progress=WORKERID)。这一条对我帮助很大,而且非常容易使用您的文档有多大?您希望每个文档的处理速度有多快?请尝试进行循环流式分发,而不是一开始就将数据拆分为6个文件。您想要的称为简单分发。你可以试试,如果你在某处安装了redis,这真的很容易。如果你想要更复杂的东西,看看。谢谢@thebjorn。但不幸的是,这并不能回答我的问题。我想要的东西,可以做负载平衡的东西。或者类似于循环的方法。@xiaohan2012实际上,这将自动进行负载平衡(假设您的限制是合理的)。工人将以他们能够处理的速度登记和处理工作。这种方法比循环法更好(更具并行性),因为在循环法中,即使工作人员没有完成最后一个切片,也需要给他一个切片——这可能会导致速度较慢的工作人员积压更多的切片。如果您想要自动启动流程的东西,请尝试使用fabric。@xiaohan2012。。。而且,循环方法需要某种中央权威,这可能成为瓶颈(尽管可能不是只有六台服务器…)
select progress, count(*)
from documents
group by progress
order by progress