我有一个Web应用程序,可以发送有关某些操作的电子邮件。因此,为此,它将请求保存在数据库中,然后一个电子邮件工作线程接收请求并发送电子邮件。电子邮件工作人员会在数据库中查看更改。
现在我希望在负载均衡器后面运行相同的Web应用程序共享同一个数据库。现在问题是当我在数据库中创建一个电子邮件请求时,在负载均衡器后面的不同机器上的类似Web应用程序内运行的电子邮件工作者可能会同时看到电子邮件的数据库条目,这将导致在同一封电子邮件中多次发送。
那么,除了显式锁定表之外,还有什么办法可以防止这种情况吗?
我已经阅读了这个问题Distributing java threads over multiple servers? ,但不知道那里提供的解决方案是否足以满足我的需求。 Terracotta似乎是解决方案,但我认为它需要将显式同步添加到代码中,不知道。
任何有关此方面的知识都会有所帮助。
答案 0 :(得分:0)
简单,低技术的解决方案是让电子邮件发送工作者只运行一次。
这可以通过将工作程序解压缩到单独的应用程序来实现,该应用程序由cron触发,或者通过使其可配置,无论Web应用程序的实例是否已激活电子邮件工作程序。在后一种情况下,您需要确保只有一个负载平衡实例的电子邮件工作者处于活动状态
缺点是电子邮件发送不会是多余的,即如果发送电子邮件的主机已关闭,则没有人发送任何电子邮件。
如果您需要冗余,您必须依赖某些分布式中间件,如上面链接的问题,或者自己实现同步机制。
对于自己的实现,您可以使用电子邮件请求中的版本号字段/列来查看乐观锁定,如Hibernate / JPA所支持(请参阅https://stackoverflow.com/a/19456821/981913)。该算法将如下所示:
答案 1 :(得分:0)
使用SQL事务锁定行以进行处理。
您的电子邮件行应添加2列,TIMESTAMP类型:processed_time,send_time但默认为NULL
您可能需要根据您使用的DB / ORM微调此过程,但总体思路仍然存在。