为了简单起见,我们假设我正在克隆twitter(我不是)。因此,每个用户都可以关注其他用户,并被其他用户关注。对于您关注的每个用户,您会收到他发送的所有推文。一切都存储在数据存储中(无论是NoSQL解决方案还是分片关系数据库)。
但是,当用户在线时,您认为让他们通过JMS接收推文是合适的,而不是轮询数据库并检索新的推文:
当然,整个事情应该在集群中运行,并且可以扩展。
但是我不确定:
在某些时候(当事情有效时)我会做一些基准测试,但我想听一些初步的评论。
答案 0 :(得分:3)
听起来很合理。您需要确保您选择的JMS实现支持可能非常多的主题 - 并非所有主题都可以优雅地完成。
我的主要设计问题是,当用户首次登录时,他的会话消息存储将为空,您必须等待它填满。那么你是不是必须打到数据库,或者这不是问题。
另外,你并没有真正利用JMS的事件驱动特性。从主题接收的消息将被转储到会话存储中以供以后检索。
由于它不是真正的事件驱动,你可以考虑使用分布式内存数据存储,例如EhCache + JGroups或JBossCache3(我强烈推荐)。新的推文将被放入这个分布式商店,读者只需要搜索那些寻找感兴趣的项目。这可能更节省内存,因为每个推文上只存储一个每个推文的副本。您也可以在系统启动时预加载缓存。
答案 1 :(得分:1)
注意:我对您在问题中描述的系统设置没有实际经验,因此以下是理论上的考虑因素。
一个因素是问题,您的用户将在下次登录时看到的内容:
案例1:JMS很好,因为队列可以记住,哪些消息已经被传递。但是等一下:这意味着,每条消息接收器必须有一个队列。
案例2:在这里,您可以真正处理每封邮件发件人的主题,并使超过x小时的邮件过期。再说一遍,JMS可能是个不错的选择。
<强>性能强>
JMS实现通常可以将消息保留在内存中,并且为了访问队列/主题中的消息,您不必搜索大型索引 - 所以我认为这应该比数据库更快,可能仍然比内存数据库更快。当节点出现故障时,您可以从后备数据库重新创建队列,也可以使用内置于某些JMS实现中的high-availability和persistence。
但我完全同意skaffman:与分布式内存数据存储相比,你将使用更多内存。 JMS的优点是,它简化了消息(以及其他一些东西)的自动过期,我不知道重新实现该功能是否是个好主意。
所以也许我会做的只是在队列中保存ID,并将实际消息保存在Java对象缓存中。这样,您将再次使用索引,但是您可以从JMS获得对象缓存的大部分内存效率。当缓存仅在发送方时,它甚至不必分发,假设来自一个发送方的所有消息都驻留在一个(复制的)节点上 - 但这可能取决于许多其他架构决策。