如何跨多个JVM节点实现计数器的最简单/最快的方法

时间:2013-10-04 13:20:32

标签: java tomcat jvm

考虑问题:

我有许多Tomcat节点,其中Web应用程序提供一些无状态内容。例如,1000个第一次请求申请必须用“a”回答,对于下一个10000用“b”回答,其余用“c”回答。

我首先考虑了消息:应用程序从某个存储中获取总服务数 - >如果它小于n,则提供内容'a' - >一旦提供了内容,应用程序就会发送一条消息 - >消息被消耗 - >总服务计数在某些存储上递增 - > ...但是在这种情况下,由于消息服务事件和存储器上的计数器增量之间的轻微(或大量的窥视加载时间)延迟,因此超调的可能性非常大。

然后我考虑设置memcached-session-manager来将计数器存储在共享会话中。但对于我的简单案例,这看起来很重要。

有人可以建议是否有多种简单的方法可以让多个JVM实例相互通信(适用于我的情况)?

3 个答案:

答案 0 :(得分:1)

对于初学者,您可以在tomcat实例之间共享会话。接收请求的tomcat服务器基本上将其会话的重复发送到所有其他tomcat服务。

我不禁想到你有一些未表达的需求驱动这个请求,但希望只问如何实现这个,而不是实际上询问如何满足需求。在这种情况下,需求不会得到满足,但要求往往是。

例如,不是担心对一个服务器的1000个请求,而是一个轮换,一个简单的多个IP地址到DNS主机名配置可以循环方式分发请求。

您还可以根据数据库协调会话。数据库提供了良好的存储功能,具有读取一致性。使用正确的配置,处理节点可以简单地读取“下一个号码”。

最后,还有其他方法,利用分布式计算。例如,请求可以由内部请求中继处理,该中继启动Paxos协议以保证所有处理节点都具有新的“下一个”号码。

所有这些技巧都很简单。但是,你很快就会解雇它们,因为它们对你来说似乎并不太简单。好吧,也许你正在寻找一个更简单的替代方案,并且没有任何伤害;然而,让两台或更多台计算机一致,可靠地同意一些项目,同时比我们所希望的那样有点棘手。随意在这个领域开展新的工作,但也许你只会发现有额外开销和复杂性的真正原因。这不是一个小问题。

---更新---

您知道,如果您可以处理请求循环风格,并放宽在服务器之间订购它们的需要,并且知道您将只有N个服务器,那么您可以实现N个不同的请求计数器。

  • 服务器1以N递增,确保count % N == 0
  • 服务器2以N递增,确保count % N == 1
  • ...
  • 服务器N-1增加N确保count % N = N-2
  • 服务器N增加N确保count % N = N-1

当然,跨服务器计数可能在短时间内不在全球范围内,但您可能会得到一些您想要的东西:

  • 每次请求的唯一计数
  • 按服务器排序请求
  • 保证所有服务器都是唯一的计数
  • 确定哪个服务器处理请求的快速方法

你缺少什么

  • 跨服务器的请求的真实排序

答案 1 :(得分:1)

如果绝对必须是正确的,并且您不希望延迟,我认为 Redis Hazlecast 是您的最佳选择。的 Particularly Redis as it has atomic count like operations 即可。虽然理论上你可以对memcache做同样的事情,但Redis是为这个确切的用例(统计计数器)而设计的。

您也可以使用像H2这样的内存数据库,或者只是将Postgres表设置为unlogged或者适用于您的RDBMS的任何内容,以便在伪内存表中保持不那么安全。关于RDBMS的烦人之处是所有RDBMS都不支持upserting aka MERGE

答案 2 :(得分:0)

以下是您订购时所需的所有选择,以及设置它们所需的大部分工作:

  1. 使用memcached-session-manager存储各种Tomcats的会话
  2. 使用像sqlite这样的轻量级数据库,并将计数器存储在表/集合
  3. 使用共享文件系统并将计数器存储在文本文件中
  4. 使用Redis或Memcahed或Ehcache或Hazelcast等轻量级缓存提供程序
  5. 使用JMS之类的消息传递并继续传递计数器