用于消息存储目的的集群NoSQL数据库应选择哪种?

7
又是一个关于选择哪种NoSQL的问题。但是,我还没有找到有人询问过这种类型的问题,即消息存储...
我已经制作了一个Erlang聊天服务器,并且已经使用MySQL来存储好友列表和“JOIN needed”信息。
我想存储用户尚未接收的消息(因为他们离线了...)并检索它们。
我已经对NoSQL进行了预选,不能使用像MongoDB这样基于RAM的范例,而且像其他范例一样无法集群。我已经将我的清单缩小到3个选择:
-Hbase -Riak -Cassandra
我知道它们的模型相当不同,其中一个使用键/值,另一个使用SuperColumns等。
到目前为止,由于其稳定的Erlang客户端库,我更喜欢Riak。
我知道我可以使用Thrift来使用Cassandra,但似乎与Erlang不太稳定(我没有得到良好的回报)。
我现在确实不知道HBase的任何事情,只知道它存在并且基于类似Cassandra和Riak的Dynamo。
所以这就是我需要做的事情:
-每个注册用户存储从1到X条消息。 -获取每个用户存储的消息数量。 -一次性检索用户的所有消息。 -一次性删除用户的所有消息。 -删除所有旧于X个月的消息
目前,我对这些NoSQL数据库非常陌生,我一直是MySQL爱好者。这就是为什么我问你这个问题,作为一个新手,是否有比我更有经验的人可以帮助我选择哪种更好,并且能够让我无需过多麻烦地完成所有想做的事情...
谢谢!

@BrianRoach:他们在这个问题上似乎不这么认为https://dev59.com/KHE85IYBdhLWcg3wNgrk 这是同样类型的问题。 - TheSquad
1
一个问题没有被下投票和关闭并不影响事实,即根据FAQ和元数据,它不合适。此外,那是2年前的事情 - 随着其他网站的增加,情况已经发生了变化。 - Brian Roach
3个回答

7
我不能代表Cassandra或Hbase发言,但让我来回答一下Riak部分。
是的,Riak适合您的场景(我见过几家公司和社交网络将其用于类似的目的)。
要实现这一点,您需要普通的Riak键/值操作,以及某种索引引擎。您的选择有(按偏好顺序):
  1. CRDT 集合。如果你的1-N集合大小相当合理(比如说,每个用户少于50条消息),你可以在CRDT Set Data Type中存储子集合的键。

  2. Riak 搜索。如果你的集合大小很大,尤其是如果你需要在任意字段上搜索对象,你可以使用Riak Search。它在后台启动Apache Solr,并根据你定义的模式对对象进行索引。它具有非常强大的搜索、聚合和统计、地理空间能力等功能。

  3. 二级索引。你可以在eLevelDB storage back end上运行Riak,并启用Secondary Index (2i)功能。

运行一些性能测试,选择最快的方法。

就架构而言,我建议使用两个桶(针对您描述的设置):一个用户桶和一个消息桶。

对消息桶进行索引。(可以通过将搜索索引与其关联或通过使用2i存储user_key来实现)。这样,您就可以执行所有必需的操作(并且消息日志不必适合内存):

  • 每个注册用户最多存储1到X条消息 - 一旦您创建了一个用户对象并获得用户密钥,存储任意数量的消息对于每个用户来说都很容易,这些消息将直接写入消息桶中,每个消息将适当的user_key作为二级索引进行存储。
  • 获取每个用户存储的消息数量 - 没有问题。通过搜索查询、检索保存键的Set对象或通过user_key的2i查询获取属于用户的消息键列表。这样可以在客户端获取计数。
  • 一次检索用户的所有消息 - 参见前一项。获取属于用户的所有消息的键列表(通过搜索、Sets或2i),然后通过为每个键批量获取值(所有官方Riak客户端都具有multiFetch功能,客户端侧)来获取实际的消息。
  • 一次删除用户的所有消息 - 非常相似。获取用户的消息键列表,然后在客户端上发出删除操作。
  • 删除所有早于X个月的消息 - 您可以在日期上添加索引。然后,检索所有早于X个月的消息键(通过搜索或2i),并对它们发出客户端删除操作。

生活中有趣的事情...在我发布这个问题3年后,我开始了另一个项目,并且有一些需要回答的问题。很可能你回答了它们!所以在这里,3年后,一个经过验证的问题和一个未来的+1;-) - TheSquad
我编辑了答案,以考虑到自那时以来出现的一些新的Riak功能,特别是搜索和数据类型。 - Dmitri Zagidulin
感谢您编辑今天功能的答案。是的,我打算查看Riak Search。当您知道如何使用它时,Solr非常棒。 - TheSquad

0

我完全不知道Riak,但是我会质疑你放弃Mongo的选择。只要关闭日志记录并且不完全限制RAM,它还是相当不错的。

我对HBase了解很多,听起来它可以轻松满足你的需求。根据你有多少用户,它可能过于复杂了。它可以轻松支持存储每个用户的许多消息,并具有自动过期写入的功能。根据你架构模式的不同,它可能或可能不是原子性的,但这对你的使用案例并不重要。

缺点是需要大量的开销才能正确设置它。在启动HBase之前,你需要了解Hadoop、运行HDFS以及确保你的namenode可靠等等。


1
我想MongoDB也是一个不错的选择,但我真的想要一个基于Dynamo的模型(没有单点故障),据我所知,MongoDB并非基于此,但我可能错了。你对Cassandra有什么负面意见吗? - TheSquad
我的想法并不是完全放弃MongoDB,但现在我还没有被说服它是集群数据库的最佳解决方案...看起来我现在选择的这三个数据库在这个主要点上是最好的,你不觉得吗? - TheSquad
当Mongo分片并且每个碎片都被复制时,它就没有单点故障。而HBase有-即HDFS NameNode。我对Cassandra了解不够,无法发表太多评论,只知道它没有单点故障,并且与HBase在能力上非常相似。 - Chris Shain

0
我建议使用分布式键/值存储,如Riak或Couchbase,并将每个用户的整个消息日志序列化(成二进制Erlang术语或JSON / BSON)作为一个值。
因此,对于您的用例,它将如下所示:
  • 为每个注册用户存储1到X条消息 - 当用户上线时,生成一个有状态的gen_server,该服务器从存储中获取并在启动时反序列化整个消息日志,接收新消息,将其附加到其日志副本中,在会话结束时终止,序列化更改的日志并将其发送到存储。
  • 获取每个用户存储的消息数量 - 获取日志,反序列化,计数;或者可能在单独的k/v对中存储计数。
  • 一次检索一个用户的所有消息 - 只需从存储中提取即可。
  • 一次删除一个用户的所有消息 - 只需从存储中删除值。
  • 删除所有早于X个月的消息 - 获取、过滤、放回。

显而易见的限制是消息日志必须适合内存。

如果您决定单独存储每个消息,那么在检索后,分布式数据库需要对它们进行排序,以便按时间顺序排列,因此这几乎无法帮助处理大于内存数据集。如果需要的话,您最终将不得不采用一些更棘手的方案。

不幸的是,消息日志很有可能无法适应内存...这就是为什么我可能会选择Cassandra,它的列式数据库看起来很有前途,如果它能够处理Twitter的推文,那么它也将适用于我的情况...(可以做更多,也可以做更少;-) - TheSquad
你也可以将消息日志分成多个页面,其中一个页面存储为一个值。我个人没有这方面的经验,但在Voxer的这个演讲中有描述:http://vimeo.com/52827773 - Joe Rideout

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接