4

我有一个应用程序,其工作方式如下:Linux 机器生成 28 种不同类型的给客户的信件。信件必须以 .docx(Microsoft Word 格式)发送。秘书维护 MS Word 模板,这些模板会根据需要自动使用。改变使用 MS Word 不是一种选择。

为了协调这一切,将文档作业放入数据库表中,并且在每台 Windows 机器上运行的 python 程序频繁地轮询数据库,锁定作业并根据需要运行它们。

我们为作业信息使用中央数据库表来协调不同的状态(“新”、“处理”、“完成”、“打印”)......以及提供准确的状态信息。

无论如何,我不喜欢客户经常轮询数据库,因为他们大部分时间都没有工作。客户端每 5 秒进行一次 hpoll。

为了避免轮询,我希望向所有客户端机器发送广播“有一些工作要做”或“检查你的数据库是否有一些工作要做”消息。

我认为某种发布/订阅消息队列可以胜任这项工作,但我不想要任何巨大的额外复杂性。

是否有零或接近零的配置/维护软件可以实现这一目标?有什么选择?

X

4

4 回答 4

6

是否有任何客观证据表明服务器上有任何重大负载?如果它有效,我会确保这里确实有问题需要解决。

一切都运行得如此顺利,以至于您看到的东西可能只会被改进,这一定是件好事!

于 2009-04-24T22:12:48.737 回答
3

是否有零或接近零的配置/维护软件可以实现这一目标?有什么选择?

可能,但是您在配置和实施时间中节省的时间可能会比您的轮询服务更严重地损害性能。SQL Server 并不是真正用来推动的(无论如何也不容易)。您可以使用某些东西来推送数据(复制服务、日志传送 - 令人讨厌的东西),但它们会比简单的轮询服务更复杂并且需要更多资源。一些选择是:

  1. 某种使用命令行调用 (sp_cmdshell) 运行可执行文件的触发器

  2. 使用 SQL Server 可以打开和运行的 COM 对象

  3. 使用 SQL 代理作业运行 VBScript(这将再次被视为“轮询”)

考虑到您已经完成的工作要简单得多,这些选项有点荒谬。

如果您担心轮询服务使用太多周期或其他东西 - 您可以随时将其限制 - 每分钟、每 10 分钟或什至每天一次轮询可能更合适 - 这将是一个商业决策,所以去吧询问业务中的某人需要多快。

简单的轮询服务相当普遍,因为它们……嗯……简单。此外,它们还具有低开销、远程稳定和容错性。不利的一面是,如果不仔细控制,他们可能会将数据库锤成灰尘。

于 2009-04-24T19:01:09.227 回答
3

消息队列可能运行良好,因为它们通常被设置为能够在不浪费资源的情况下阻塞一段时间。但是对于 MySQL,我认为这不是一个选择。

如果你只是想减少数据库的负载,你可以创建一个单行表:最新的作业 ID。然后客户端只需将其与他们的最后一个 ID 进行比较,以查看他们是否需要对真实表运行完整的轮询。如果现在是问题,这种方式应该大大减少开销。

于 2009-04-24T22:03:59.147 回答
1

与 Postgres 和 SQL Server(或 CouchDb 之类的对象存储)不同,MySQL 不发出数据库事件。但是,您可以使用一些编码模式来模拟这一点。

如果您有一个或多个要监视的表,您可以在这些表上创建触发器,将一行添加到记录要处理的事件队列的“更改”表中。您的触发器过滤您关心的数据更改子集,并在更改表中为您希望执行的每个事件创建记录。因为这种模式对事件进行排队持久化,所以即使处理这些事件的工作人员出现中断,它也能很好地工作。

您可能认为 MyISAM 是更改表的最佳选择,因为它主要执行写入(如果您不需要在数据库服务器中断之间持久保存事件,甚至是 MEMORY)。但是,请记住,Memory 和 MEMORY 以及 MyISAM 都只有全表锁,因此在对 MEMORY 和 MyISAM 表执行插入操作时,您对 InnoDB 表的触发器可能会遇到瓶颈。如果您将 ON DELETE CASCADE 与另一个 InnoDB 表一起使用(要求两个表使用相同的引擎),您可能还需要 InnoDB 用于更改表。

您还可以使用SHOW TABLE STATUS检查更改表的最后更新时间来检查是否有要执行的操作。此功能不适用于 InnoDB 表。

这些文章更深入地描述了一些在 MySQL 中实现队列甚至避免轮询的替代方法!

于 2016-07-27T23:43:56.173 回答