PHP中分布式系统的剖析

时间:2009-10-04 17:44:33

标签: php database-design sqlite couchdb distributed

我遇到了一个问题,这让我很难找到理想的解决方案,为了更好地解释它,我将在这里公开我的方案。

  

我有一台接收订单的服务器   来自几个客户。每个客户都会   提交一组重复的任务   应该在某些指定的地方执行   间隔,例如: 客户端A提交任务   应该每次执行的AA   2009-12-31和之间的分钟   2010-12-31 ;所以,如果我的数学是正确的   这是一个约525 600个操作   一年,给予更多的客户和任务   让服务器处理所有这些任务是不可行的,所以我   提出了工人的想法   机器。服务器将被开发   关于PHP。

     

工人机器通常很便宜   基于Windows的计算机,我会   在我家或我的工作场所主持,   每个工人都有一个专门的   互联网连接(动态IP )   和UPS,以避免停电。每   worker也将每次查询服务器   通过网络服务电话30秒左右,   获取下一个待处理作业并进行处理。   一旦工作完成,工人就会   将输出提交给服务器并请求   无限的新工作等等。如果   需要扩展系统I   应该只是建立一个新的工人和   整个事情应该无缝运行。   将开发工作者客户端   用PHP或Python。

     

在任何时候我的客户都应该   能够登录到服务器并检查   他们订购的任务的状态。

现在这里是棘手的部分:

  • 我必须能够重建 已经处理过的任务,如果有的话 服务器发生故障的原因。
  • 工人不是客户特定的, 一个工人应该为...处理工作 任何给定数量的客户。

我对通用数据库设计以及要使用的技术存有疑问。

最初我想过使用几个 SQLite 数据库和在服务器上加入所有数据库,但我无法弄清楚如何按客户端分组来生成作业报告

我从未真正使用过以下任何技术: memcached CouchDB Hadoop 等等,但我会想知道这些中的任何一个是否适合我的问题,如果是,你推荐给新手的是“分布式计算”(或者这是平行的?)和我一样。 请记住,工作人员拥有动态IP。

就像我之前所说的那样,我也遇到了一般的数据库设计问题,部分原因是因为我还没有选择任何特定的R(D)DBMS,但是我认为这个问题与DBMS不相关选择与排队系统相关 ...我应该预先计算特定作业的所有绝对时间戳并拥有大量时间戳,执行并将其标记为完成升序或者我应该有一个更聪明的系统,如“ 时间戳模数60 == 0 - >执行 ”。这个“聪明”系统的问题是某些工作不会按顺序执行它们应该是因为有些工作人员可能在等待什么都不做而其他工作负载过重。 你有什么建议?

PS:我不确定这个问题的标题和标签是否恰当地反映了我的问题和我想要做的事情;如果没有,请相应地进行编辑。

感谢您的投入!

@timdev:

  1. 输入将是一个非常小的JSON编码字符串,输出也将是一个JSON enconded字符串,但稍大一点(大约1-5 KB)。
  2. 输出将使用Web上的几个可用资源计算,因此主要瓶颈可能是带宽。数据库写入也可以是一个 - 取决于R(D)DBMS。

7 个答案:

答案 0 :(得分:15)

看起来你正在重新创建Gearman。这是Gearman的介绍:

  

Gearman提供了一个通用的应用程序   将工作分配给其他人的框架   机器或过程更好   适合做这项工作。它允许你   要并行工作,加载   平衡处理,并打电话   语言之间的功能。有可能   用于各种应用,   从高可用性网站到   数据库复制的传输   事件。换句话说,就是这样   神经系统如何分配   处理沟通。

您可以用PHP编写客户端和后端工作程序代码。


关于为Windows编译的Gearman Server的问题:我不认为它是在为Windows预先构建的整洁软件包中提供的。 Gearman仍然是一个相当年轻的项目,他们可能还没有成熟到为Windows制作可立即运行的发行版。

Sun / MySQL员工Eric Day和Brian Aker于2009年7月在OSCON为Gearman提供tutorial,但他们的幻灯片仅提及Linux软件包。

这是Perl CPAN测试人员项目的链接,表明可以使用Microsoft C编译器(cl.exe)在Win32上构建Gearman-Server,并通过测试:http://www.nntp.perl.org/group/perl.cpan.testers/2009/10/msg5521569.html但是我你猜你必须下载源代码并自己构建它。

答案 1 :(得分:4)

Gearman似乎是这种情况的完美候选者,您甚至可能希望将Windows计算机虚拟化为每台计算机的多个工作节点,具体取决于您需要多少计算能力。

齿轮手中的persistent queue system也可防止当工人或齿轮装置服务器崩溃时工作丢失。在服务重新启动之后,队列只会在崩溃/重新启动之前继续停止,您不必在应用程序中处理所有这些,这是一个很大的优势并节省了大量的时间/代码

制定一个自定义解决方案可能会有效,但齿轮机特别是持久性队列的优势在我看来,这可能是目前最好的解决方案。我不知道有关齿轮箱的Windows二进制文件,但我认为它应该是可能的。

答案 2 :(得分:3)

更简单的解决方案是拥有一个连接多个php节点的单个数据库。如果您使用正确的RDBMS(MSql + InnoDB会这样做),您可以让一个表充当队列。然后,每个工作人员将从中提取任务以进行处理,并在完成时将其写回数据库,使用事务和锁定进行同步。这取决于输入/输出数据的大小。如果它很大,这可能不是最佳方案。

答案 3 :(得分:3)

我会避免使用sqlite进行这类任务,虽然它对于小型应用程序来说是一个非常精彩的数据库,它不能很好地处理并发性,它只有一个锁定策略,即锁定整个数据库并保持锁定直到sinlge交易完成。

考虑具有工业强度并发和锁管理的Postgres,可以非常好地处理多个同时交易。

这听起来像排队的工作!如果您在Java世界中,我会为您的解决方案推荐基于JMS的架构。有一个'dropr'项目在php中做类似的事情,但它都是相当新的,所以它可能不适合你的项目。

无论你使用哪种技术,你都应该选择一种“自由市场”解决方案,在这种解决方案中,工作者线程尽可能快地消耗可用的“工作”,而不是“中央流程分配任务来选择工人”的“命令经济”。 / p>

答案 4 :(得分:3)

主服务器和几个工作人员的设置看起来就像你的情况一样。

在主服务器上我会在主 - 主复制中安装MySQL(Percona InnoDB版本is stable and fast),这样您就不会有单点故障。 主服务器将托管一个API,工作人员将每隔N秒提取一次。主服务器将检查是否有可用的作业,如果是,则必须标记该作业已分配给工作者X并将相应的输入返回给工作者(所有这些都通过HTTP)。 此外,您可以在此处存储工作人员的所有脚本文件。

关于工作人员,我强烈建议您安装Linux发行版。在Linux上,设置计划任务更容易,总的来说,我认为它更适合这项工作。 使用Linux,您甚至可以使用完美配置的工作人员创建live cd或iso映像,并在所需的所有计算机上快速轻松地安装它。 然后设置一个cron作业,它将与主服务器RSync一起更新/修改脚本。通过这种方式,您只需在一个位置(主服务器)更改文件,所有工作人员都将获得更新。

在此配置中,您不关心IP或工作人员数量,因为工作人员正在连接到主服务器,反之亦然。

工作人员的工作非常简单:向API询问工作,执行此操作,通过API发回结果。冲洗并重复: - )

答案 5 :(得分:2)

您可以使用RabbitMQActiveMQ之类的消息传递系统作为系统的核心,而不是通过SQL重新发明排队轮。这些系统中的每一个都提供AMQP协议并具有硬盘支持的队列。在服务器上,您有一个应用程序根据您的计划将新作业推送到“工作”队列,另一个应用程序将结果从“结果”队列写入数据库(或以其他方式对其进行操作)。

所有工作人员都连接到RabbitMQ或ActiveMQ。他们将工作从工作队列中弹出,完成工作并将响应放入另一个队列。完成后,他们确认原始工作请求说“完成”。如果某个工作程序断开连接,该作业将恢复到队列中,以便其他工作人员可以执行此操作。

队列以外的所有内容(职位描述,客户详细信息,已完成的工作)都可以存储在数据库中。但任何实时应该放在其他地方。在我自己的工作中,我正在传输实时电源使用数据,并且让很多人在数据库中进行轮询,这是一个坏主意。我written about live data in my system

答案 6 :(得分:1)

我认为你正在与一个主要的工作经销商和工人一起朝着正确的方向前进。我希望他们通过HTTP进行通信。

我会选择C,C ++或Java作为客户端,因为它们具有运行脚本的功能(c中的execvp,Java中的System.Desktop.something)。作业可能只是脚本的名称和该脚本的参数。您可以让客户端返回作业的状态。如果作业失败,您可以重试它们。您可以让客户每分钟轮询一次作业(或每隔x秒,并使服务器整理作业)

PHP适用于服务器。

MySQL可以很好地用于数据库。我只想制作两个时间戳:开始和结束。在服务器上,我会寻找WHEN SECONDS == 0