3

关于 Cassandra,我有一点不明白。比如说,我有一个类似于 Facebook 的网站,人们可以在其中分享、点赞、评论、上传图片等。

现在,假设我想获得我朋友所做的所有事情:

  • Username1 喜欢你的评论
  • 用户名 2 更新了他的头像

等等。

因此,经过大量阅读,我想我需要做的是为每一件事创建新的列族,例如:user_likes user_comments, user_shares. 基本上,你能想到的任何事情,即使在我这样做之后,我仍然需要为大多数列创建二级索引,以便我可以搜索数据?即便如此,我怎么知道哪些用户是我的朋友?我是否需要先获取所有朋友的 id,然后为每个用户 id 搜索所有这些 Column Families?

编辑 好的,所以我做了更多的阅读,现在我对事情的理解更好了,但我仍然无法真正弄清楚如何构建我的表格,所以我会设置一个赏金,我想得到一个清楚的例子来说明我的如果我想以这种顺序存储和检索数据,表应该看起来像:

  • 全部
  • 喜欢
  • 评论
  • 收藏夹
  • 下载
  • 分享
  • 留言

所以假设我想检索我所有朋友或我关注的人的最后十个上传文件,这就是它的样子:

John uploaded song AC/DC - Back in Black 10 mins ago

评论和分享之类的每件事都与此类似...

现在最大的挑战可能是一起检索所有类别的最后 10 个东西,所以列表将是所有东西的混合......

现在我不需要一个完整详细的表格的答案,我只需要一些非常清晰的例子来说明我将如何像我一样构建和检索mysql数据joins

4

3 回答 3

5

使用 sql,您可以构建表以规范化数据,并使用索引和连接进行查询。使用 cassandra,您无法做到这一点,因此您需要构建表以服务于您的查询,这需要非规范化。

您想查询您的朋友上传的项目,一种方法是每个用户没有一个表,并且每当该用户的朋友上传某些内容时写入该表。

friendUploads { #columm family
    userid { #column 
        timestamp-upload-id : null #key : no value
    }
 }

举个例子,

friendUploads {
    userA {
         12313-upload5 : null
         12512-upload6 : null
         13512-upload8 : null
    }
}

friendUploads {
    userB {
         11313-upload3 : null
         12512-upload6 : null
    }
}

请注意,上传 6 被复制到两个不同的列,因为上传 6 的人是用户 A 和用户 B 的朋友。

现在要查询朋友的朋友上传显示,在 userid 列上做一个限制为 10 的 getSlice。这将返回前 10 个项目,按键排序。

要将最新项目放在首位,请使用反向比较器,将较大的时间戳排序在较小的时间戳之前。

此代码的缺点是当用户 A 上传歌曲时,您必须执行 N 次写入来更新friendUploads 列,其中 N 是用户 A 的朋友的人数。

对于与每个 timestamp-upload-id 键关联的值,您可以存储足够的信息来显示结果(可能在 json blob 中),或者您可以不存储任何内容,并使用 uploadid 获取上传信息。

为避免重复写入,您可以使用如下结构,

userUploads { #columm family
    userid { #column 
        timestamp-upload-id : null #key : no value
    }
 }

这存储特定用户的上传。现在当想要显示用户 B 的朋友的上传时,您必须进行 N 次查询,用户 B 的每个朋友一个,并将结果合并到您的应用程序中。查询速度较慢,但​​写入速度较快。

最有可能的是,如果用户可以有数千个朋友,您会使用第一种方案,并进行更多的写入而不是更多的查询,因为您可以在用户上传后在后台进行写入,但查询必须在用户进行时进行在等待。

作为非规范化的一个例子,看看当单击发生时 twitter rainbird 做了多少次写入。每次写入用于支持单个查询。

于 2012-10-14T18:54:48.830 回答
1

在某些方面,您“可以”将 noSQL 视为关系存储。在其他情况下,您可以进行非规范化以使事情变得更快。例如,PlayOrm 的 @OneToMany 像这样存储了许多

user1 -> friend.user23, friend.user25, friend.user56, friend.user87

这是宽行方法,因此当您找到您的用户时,您拥有他朋友的所有外键。每行可以是不同的长度。您可能还存储了反向引用,因此用户可能引用了将他标记为朋友但他没有将其标记回来的人(我们称其为好友),因此您可能有

user1 -> friend.user23, friend.user25, buddy.user29, buddy.user37

请注意,如果设计正确,您可能不需要“搜索”数据。也就是说,使用 PlayOrm,您仍然可以执行 Scalable SQL 和连接(您只需要弄清楚如何对表进行分区,以便它可以扩展到数万亿行)。

一行中可以有数百万列,也可能只有 10 列。实际上,本月我们正在更新 PlayOrm 中的大量文档和 noSQL 模式,所以如果您密切关注这一点,您还可以了解更多信息关于那里的一般noSQL。

院长

于 2012-10-12T13:11:21.383 回答
1

将每个数据库查询视为对另一台机器上运行的服务的请求。您的目标是尽量减少这些请求的数量(因为每个请求都需要网络往返)。

这是与 RDBMS 范式的主要区别:在 SQL 中,您通常会使用连接和二级索引。在 cassandra 中,连接是不可能的,因为相关数据将驻留在不同的服务器上。诸如物化视图之类的东西在 cassandra 中用于相同目的(通过单个查询获取所有相关数据)。

我建议阅读这篇文章: http: //maxgrinev.com/2010/07/12/do-you-really-need-sql-to-do-it-all-in-cassandra/

并查看 twissandra 示例项目https://github.com/twissandra/twissandra 这是您描述的项目类型的优化技术的不错集合。

于 2012-10-13T19:12:30.447 回答