投票有啥问题?

Posted

技术标签:

【中文标题】投票有啥问题?【英文标题】:What is wrong with polling?投票有什么问题? 【发布时间】:2008-11-26 10:52:20 【问题描述】:

我最近听到一些开发人员说他们只是轮询一些东西(数据库、文件等)以确定什么时候发生了变化,然后运行一个任务,比如导入。

我真的反对这个想法,我觉得利用Remoting、WCF等可用的技术比轮询要好得多。

但是,我想找出为什么其他人更喜欢一种方法而不是另一种方法的原因,更重要的是,我如何才能让其他人相信,在这个时代,民意调查是错误的?

【问题讨论】:

仅供参考:远程处理和 WCF 进行轮询。 在一定程度上是的,但与某些开发人员明确使用轮询的方式不同,即每分钟轮询一次数据库。 我有类似的情况,我在多个 ftp 位置多次轮询以获取更新的文件,处理这种情况的最佳方法是什么? 除了“因为它更容易”之外,您需要进行轮询的另一个常见原因是当被轮询的事物无法更改为推送通知时(或者因为它不在您的控制;改变它的成本或风险被认为太高等) 我完全同意你的看法,这是错误的,它绝对没有充分的理由占用资源。人们这样做的原因是因为它是最简单的选择。 【参考方案1】:

轮询本身并没有“错误”。

很大程度上取决于它的实施方式和目的。如果您真的关心立即通知更改,那将非常有效。您的代码处于紧密循环中,不断轮询(询问)资源是否已更改/更新。这意味着您会尽快收到通知,告知您有所不同。但是,您的代码没有做任何其他事情,并且在对相关对象的多次调用方面存在开销。

如果您不太关心即时通知,则可以增加轮询之间的间隔,这也可以很好地工作,但选择正确的间隔可能会很困难。太长,您可能会错过关键更改,太短,您又会回到第一种方法的问题。

诸如中断或消息等替代方案可以在这些情况下提供更好的折衷方案。您会在实际可能的情况下尽快收到更改通知,但这种延迟不是您可以控制的,它取决于组件本身是否及时传递状态更改。

轮询有什么“错误”?

可能会占用资源。 它可能会受到限制(尤其是当您有很多事情想了解/民意调查时)。 这可能有点矫枉过正。

但是……

本质上并没有错。 它可能非常有效。 很简单。

【讨论】:

“这意味着您会尽快收到通知,告知您有什么不同。”这不是取决于轮询间隔以及发生任何事情时您的距离有多近吗? 在某些情况下轮询可能比消息更有效。这取决于“事件”的数量和频率。作为一个有些人为的例子,考虑一个温度计,它每秒测量某个温度 100 次并发送更新。如果每次更新都使用单独的消息,则每秒需要处理 100 条消息。但假设您只关心每 5 秒测量一次温度。在这种情况下,每 5 秒轮询一次将比处理 500 条消息更有效。【参考方案2】:

当今时代使用轮询的例子:

电子邮件客户端轮询新邮件(即使使用 IMAP)。 RSS 阅读器轮询提要的更改。 搜索引擎轮询其索引页面的更改。 *** 用户通过点击“刷新”来轮询新问题 ;-) Bittorrent 客户端轮询跟踪器(我认为,使用 DHT 并相互轮询)以了解集群中的变化。 多核系统上的自旋锁可能是核之间最有效的同步,以防延迟太短而没有时间在该核上调度另一个线程,在另一个核执行我们正在等待的任何事情之前.

有时根本无法获得异步通知:例如,要用推送系统替换 RSS,服务器必须知道阅读提要的每个人并有联系他们的方式。这是一个邮件列表——这正是 RSS 旨在避免的事情之一。因此,我的大多数示例都是网络应用程序,这很可能是一个问题。

其他时候,即使有异步通知,轮询也足够便宜。

对于本地文件,原则上通知更改可能是更好的选择。例如,如果您永远戳它,您可能(可能)阻止磁盘旋转,尽管操作系统可能会再次缓存。如果您每秒轮询一个每小时只更改一次的文件,您可能会不必要地占用机器处理能力的 0.001%(或其他)。这听起来很小,但是当您需要轮询 100,000 个文件时会发生什么?

但实际上,无论您做什么,开销都可能可以忽略不计,因此很难对更改当前有效的代码感到兴奋。最好的办法是注意轮询在您要更改的系统上导致的特定问题 - 如果您发现任何问题,请提出这些问题,而不是试图提出反对所有轮询的一般论点。如果你没有找到任何东西,那么你就无法修复没有损坏的东西......

【讨论】:

天啊!!我是一个投票设备。 :O【参考方案3】:

从原则上讲,轮询可能被认为是不好的原因有两个。

    这是对资源的浪费。您很可能会在未发生更改时检查更改。花费在此操作上的 CPU 周期/带宽不会导致更改,因此本可以更好地花费在其他方面。

    轮询在特定时间间隔内完成。这意味着在下一次间隔过去之前,您不会知道发生了更改。

最好通知更改。这样您就不会轮询尚未发生的更改,并且您会在收到通知后立即知道更改。

【讨论】:

请注意,有时轮询可以节省资源。它为您执行繁重工作的频率(即轮询间隔)设置了一个上限。不经常相关,但在相关时可能很重要。 当然,大多数提供更改通知的事物本身都是轮询以检测该更改。在某些时候,在许多情况下,投票是第一位的。【参考方案4】:

轮询很容易做到,非常简单,就像任何程序代码一样简单。不轮询意味着您进入了异步编程的世界,这并不容易,甚至有时会变得具有挑战性。

与任何系统中的所有事物一样,阻力较小的路径通常更常见,因此总会有程序员使用轮询,甚至是优秀的程序员,因为有时不需要使用异步模式使事情复杂化。

我总是热衷于避免轮询,但有时我还是会进行轮询,尤其是当异步处理的实际收益不是那么大时,例如在处理一些小的本地数据时(当然你会更快一点,但用户不会注意到这种情况下的差异)。因此,恕我直言,这两种方法都有空间。

【讨论】:

+1 表示常识:“有时不需要使用异步模式使事情复杂化。”【参考方案5】:

客户端轮询的扩展性不如服务器通知。想象一下成千上万的客户向服务器询问“有什么新数据吗?”每 5 秒。现在想象一下服务器保存一个客户端列表来通知新数据。服务器通知可以更好地扩展。

【讨论】:

这里很好,我发现现代程序员在处理器、空间和带宽问题上很草率,因为他们有一个有趣的想法,认为这些事情会无限改善,但最终我们会达到这一点不可能再改进这些东西了。异步通知并不是人们所说的魔鬼,任何在现代操作系统上编写 GUI 的人都会一直处理异步通知。【参考方案6】:

我认为人们应该意识到,在大多数情况下,即使在事件或中断驱动的情况下,也会在某种程度上进行轮询,但是您与执行轮询的实际代码是隔离的。真的,这是最理想的情况……将自己与实施隔离开来,只处理事件。即使您必须自己实现轮询,也要编写代码以使其隔离,并独立于实现来处理结果。

【讨论】:

这并不总是准确的。在对象属性发生变化的情况下,对象本身可以设置在设置属性时发生的通知。在这种情况下,不一定会发生轮询,尽管在对象实际检查旧值和新值之间的差异的情况下它肯定会发生。【参考方案7】:

关于轮询的事情是它有效!它可靠且易于实施。

池的成本可能很高 - 如果您每分钟扫描数据库以查找更改,而一天只有两次更改,那么您会消耗大量资源以获得非常小的结果。

但是,任何通知技术的问题在于,它们实施起来要复杂得多,而且它们不仅不可靠,而且(这是一个很大的问题)您无法轻易判断它们何时不工作。

因此,如果您确实放弃了对其他技术的轮询,请确保它可供普通程序员使用并且非常可靠。

【讨论】:

我同意你的观点,在我当前的应用程序中,我正在执行相同的轮询机制并检查文件更新,但它非常耗费资源并且占用大量资源,最好的最佳处理方式是什么情况如何?【参考方案8】:

它很简单 - 轮询很糟糕 - 效率低下、浪费资源等。总有某种形式的连接可以监控某种事件,即使没有选择“轮询”。

那么为什么要加倍努力并实施额外的投票。

回调是最好的选择 - 只需要担心将回调与您当前的流程联系起来。在底层,正在进行轮询以查看连接是否仍然存在。

如果你一直打电话/打电话给你的女朋友而她从来没有接听,那为什么还要继续打电话呢?只需留言,等她“回电”;)

【讨论】:

您可以设置控制以确保远程对象始终处于有效状态,或者报告无法自行排序的问题。或者继续类比,让应答电话持续发出哔哔声,以便 gfriend 立即注意到它,或者让它发送一个 txt 以警告其他人她可能有麻烦。【参考方案9】:

我偶尔会在某些情况下使用轮询(例如,在游戏中,我会在每一帧轮询键盘状态),但绝不会在仅进行轮询的循环中进行轮询,而是将轮询作为检查(有资源 X改变了吗?如果是,做一些事情,否则处理其他事情,稍后再检查)。不过一般来说,我避免轮询支持异步通知。

原因是我不会花费资源(CPU 时间等)来等待某事发生(尤其是如果这些资源一开始就可以加速那件事的发生)。在我使用轮询的情况下,我不会闲着等待,而是在其他地方使用资源,所以这不是问题(至少对我而言)。

【讨论】:

【参考方案10】:

如果您正在轮询文件的更改,那么我同意您应该使用在发生这种情况时可用的文件系统通知,现在大多数操作系统都提供这些通知。

在数据库中,您可以触发更新/插入,然后调用您的外部代码来执行某些操作。但是,可能只是您不需要即时操作。例如,您可能只需要在 15 分钟内将数据从不同网络上的数据库 A 获取到数据库 B。数据库 B 可能无法从数据库 A 访问,因此您最终会从数据库 B 或作为在数据库 B 附近运行的独立程序进行轮询。

另外,轮询是一个非常简单的程序。它通常是在时间限制很短的情况下完成的第一步实施,并且因为它运行得很好,所以它仍然存在。

【讨论】:

【参考方案11】:

我在这里看到很多答案,但我认为最简单的答案是它自己的答案:

因为(通常)编写轮询循环的代码比为回调构建基础架构要简单得多。

然后,您会得到更简单的代码,如果它后来成为瓶颈,可以很容易地理解并重新设计/重构为其他东西。

【讨论】:

【参考方案12】:

这不是在回答您的问题。但实际上,尤其是在这个处理器周期便宜且带宽很大的“时代”中,轮询对于某些任务来说实际上是一个很好的解决方案。

好处是:

便宜 可靠 可测试 灵活

【讨论】:

我很高兴你用“一些任务”来限定它,因为我们拥有无限的处理能力、空间或带宽的想法本质上是有限的。最终,我们将达到处理器的速度、3.5 英寸硬盘驱动器可以存储多少数据以及互联网连接可以压缩多少数据的极限。这种想法无法扩展。【参考方案13】:

我同意避免投票是一项好政策。但是,关于Robert's post,我想说的是,在此处提到的问题不是那么大的问题的情况下,轮询的简单性可以使其成为一种更好的方法,因为异步方法通常可读性较差且难以维护,更不用说可能潜入其实现的错误。

【讨论】:

【参考方案14】:

与所有事情一样,这取决于。我工作的一个大型高事务系统目前使用 SQL 通知(在 SQL Server 中加载的 DLL,由扩展 SP 从某些表上的触发器调用。DLL 然后通知其他应用程序有工作要做)。

但是,我们正在远离这一点,因为我们实际上可以保证会有工作持续进行。因此,为了降低复杂性并实际加快速度,应用程序将处理它们的工作并立即再次轮询数据库以获取新工作。如果没有,它会在一小段时间后重试。

这似乎工作得更快,更简单。然而,应用程序的另一部分体积小得多,并不能从使用这种方法的速度提高中受益——除非轮询间隔非常小,这会导致性能问题。所以我们在这部分保持原样。所以合适的时候是好事,但每个人的需求不一样。

【讨论】:

【参考方案15】:

这里是推拉的相对优点的一个很好的总结: https://stpeter.im/index.php/2007/12/14/push-and-pull-in-application-architectures/

我希望我可以将它进一步总结到这个答案中,但有些事情最好不要删节。

【讨论】:

【参考方案16】:

在考虑 SQL 轮询时,在 VB6 时代,您曾经能够使用 WithEvents 关键字创建记录集,这是异步“侦听”的早期体现。

我个人总是会在轮询之前寻找一种使用事件驱动实现的方法。如果无法手动实现以下任何一项可能会有所帮助:

sql服务代理/依赖类 某种队列技术(RabbitMQ 或类似的) UDP 广播 - 有趣的技术,可以 使用多个节点侦听器构建。但在某些网络上并不总是可行的。

其中一些可能需要对您的项目进行轻微的重新设计,但在企业世界中可能是比轮询服务更好的途径。

【讨论】:

【参考方案17】:

同意异步/消息传递通常更好的大多数响应。我完全同意罗伯特古尔德的回答。但我想再补充一点。

一个补充是投票可以用一块石头杀死两只鸟。在一个特定的用例中,我参与的一个项目使用了数据库之间的消息队列,但从应用程序服务器轮询到其中一个数据库。由于从应用服务器到数据库的网络偶尔会出现故障,因此额外使用轮询来通知应用网络问题。

最后,在考虑到可扩展性的情况下,将最有意义用于用例。

【讨论】:

【参考方案18】:

我正在使用轮询来检查文件的更新,因为我在具有不同操作系统类型的异构系统中获取有关该文件的信息,其中一种非常旧。如果文件位于具有不同操作系统的远程系统上,Linux 的通知将不起作用,因为该信息不会传输,但轮询有效。这是一个低带宽检查,所以它不会伤害任何东西。

【讨论】:

以上是关于投票有啥问题?的主要内容,如果未能解决你的问题,请参考以下文章

如何选择评论数、投票总和以及活跃用户是不是投票

公开投票和避免多次投票:使用 cookie 还是 IP?

区块链投票系统概述

投票系统

复用在线投票软件 手机投票,二维码投票 微信投票

设计页面 投票系统