4

对于社交网站,我需要为每个实体(以及数百万个此类实体)存储经常修改的列表,这些列表是:

  • 经常附加到
  • 经常阅读
  • 有时减少
  • 列表由主键键控

我已经在 RDBMS 中存储了一些其他类型的数据。我知道我可以将这些列表作为多对多关系存储在 RDBMS 中,如下所示:创建一个listItems包含两列listId&&的表listItem以生成任何特定列表,只需SELECT查询所有记录WHERE listId = x。但是当涉及到高可伸缩性时,以这种方式在 RDBMS 中存储列表并不是很理想。相反,我想以自然的方式存储准备好的列表,以便最大化检索性能。因为我需要为用户获取大约数百个这样的列表,所以每当我用户登录并查看页面时。

那么我该如何解决呢?应该为这些数据使用什么样的数据库,可能是提供添加可变列以主键键控的数据库,比如 Cassandra ?

4

7 回答 7

5

我使用了相同的方法,即为每条记录存储一个 2 列的行,我将其转换为带有格式化 html 的 txt 文件,然后我们将其更改为 json,最后更改为 mongodb。

但是由于你操作频繁,我建议cassandra、hbase和googles大表实现,比如accumulo cloudata和hypertable。

Cloudata 可能是适合您的选择。

于 2013-08-27T05:56:59.287 回答
3

正如您所指出的,该解决方案必须是高性能和可扩展的:我建议您使用 Redis 及其 LIST 数据结构和 O(1) 插入和 O(N) 提取(N - 要提取的元素,考虑到您最后提取列表中的那些)并使用一些散列算法水平扩展它。我不知道您要存储多少数据以及有多少机器可用,但绝对是性能方面的最佳选择,因为没有什么比内存访问速度更快了。

如果数据量很大并且您不能将其全部保存在 RAM 中,那么 Cassandra 可以完成这项工作 - 存储按时间排序的列表非常适合使用上面提到的 Zanson 分区策略。

再想一想:您说读取性能必须是最大的,一旦用户登录,您将需要为该用户获取数百个列表。为什么不为每个用户准备一个列表?这样会有更多的写入,但读取将得到优化,因为您只需要从一个列表中获取最新条目。我不确定这是否适合您的任务,只是一个想法。:)

于 2013-09-02T11:14:02.933 回答
2

Cassandra 原生支持存储集合/地图/列表。如果您的查询总是将整个事情拉下来,那么它们是处理此类事情的一种非常简单的方法。

http://www.datastax.com/dev/blog/cql3_collections http://cassandra.apache.org/doc/cql3/CQL.html#collections

如果您的列表与用户相关联,您可以在用户行/分区上创建不同的列,然后对多个列表的查询将很快,因为它们都将位于给定用户的同一分区中。

于 2013-08-27T16:21:15.893 回答
2

我会推荐 SSDB(https://github.com/ideawu/ssdb),一个 Google leveldb 网络包装器。SSDB被设计用来存储集合数据,例如list、map、zset(sorted set)。你可以像这样使用它:

ssdb->hset(listId, listItem1);
ssdb->hset(listId, listItem2);
ssdb->hset(listId, listItem3);
...
list = ssdb->hscan(listId, 100);
// now list = [listItem1, listItem2, listItem3, ...]

一张地图中的项目数量仅限于硬盘大小。另一个解决方案是 Redis,但 Redis 将所有数据存储到内存中(比如不超过 30GB),因此它可能不适合您的项目。

SSDB 支持 C++、PHP、Python、Java、Lua 和更多客户端。

于 2013-08-27T16:10:05.277 回答
1

Cassandra 可以很好地用于此类用例。为返回的数据集/查询创建任意数量的列族。Cassandra 最适用于非规范化数据或 1:m、m:m 关系等集合。

于 2013-08-29T11:25:51.400 回答
1

我知道您不想考虑关系数据库,但我认为对于这种简单的情况,关系数据库还有一个可扩展的解决方案。主要好处是您不需要维护单独的数据库系统。

为了获得可扩展性,所有 NoSQL 解决方案都将您的数据分布在多个节点上。您可以在应用程序代码中执行此操作,将数据分散到多个关系数据库中。为了保持负载平衡,您可能需要偶尔移动数据,但只需为每 N 个列表生成一个新数据库就足够了。

于 2013-09-02T22:27:54.273 回答
0

在 cassandra 中,您可以拥有宽行,每行最多 2B 列......如果这对于实体的累积列表项目来说已经足够了,您可以将整个实体的列表存储在一行中,然后将它们一起检索。使用 cassandra 的“复合列”,您可以按顺序存储每个列表的元素并按顺序存储,并且可以在需要时删除单个列(列表项),并且在插入时只需要插入一列...

像这样的东西:(!)

      |list_1_Id : item1Id |list_1_Id : item2Id | list_2_Id : item1Id |...| list_n_Id : item3Id |
entity|     item1Value     |     item2Value     |     item1Value      |...|     item3Value      |

所以实际上你处理的是列(=项目)而不是列表......它使你的工作更容易。取决于您的列表大小考虑器,使用将实体的行拆分为多行......像这样:(!)

                 |  item1Id   |  item2Id   |  item3Id   |  item4Id   |...
entiId_list_1_Id | item1Value | item2Value | item3Value | item4Value |...
                 |  item1Id   |  item2Id   |  item3Id   |  item4Id   |...
entiId_list_2_Id | item1Value | item2Value | item3Value | item4Value |...
...

并且您可以将 itemValue 放在列名中并将列值留空以减小大小...例如,您可以通过简单地插入一个新项目: //如果它们有任何插入 entityList[entityId][ 的列,则按它们的 id 排序listId][itemId] = 项目值;或 //列按其值排序插入 entityList[entityId][listId][itemvalue] = nothing; 和删除:从 entityId='d' 和 listId='o' 和 itemId='n' 的 entityList 中删除;

或者通过您的应用程序,您可以使用像Hector这样的富客户端来完成...

于 2013-08-27T07:08:14.803 回答