构建cassandra数据库

时间:2012-10-12 11:40:53

标签: nosql cassandra

我不了解卡桑德拉的一件事。比方说,我有类似Facebook的网站,人们可以在这里分享,评论,上传图片等等。

现在,让我们说,我想得到我朋友所做的所有事情:

  • 用户名1喜欢你发表评论
  • 用户名2更新了他的个人资料照片

等等。

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

修改 好吧,所以我做了一些更多的阅读,现在我理解的东西好一点,但我仍然无法弄清楚如何构建我的表,所以我将设置一个赏金,我想得到一个明确的例子我的表如何应该看起来好像我想以这种顺序存储和检索数据:

  • 所有
  • 喜欢
  • 评论
  • 收藏夹
  • 下载
  • 消息

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

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

评论和分享等所有内容都与此类似......

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

现在我不需要一个完整详细的表格的答案,我只需要一些非常明确的例子,说明如何构建和检索数据,就像我在mysql joins中所做的那样

3 个答案:

答案 0 :(得分: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会复制到两个不同的列,因为upload6的用户是用户A和用户B的朋友。

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

要先放入最新的项目,请使用reverse comparator,在较小的时间戳之前对较大的时间戳进行排序。

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

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

为避免重复写入,您可以使用

之类的结构
userUploads { #columm family
    userid { #column 
        timestamp-upload-id : null #key : no value
    }
 }

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

最有可能的情况是,如果用户可以拥有数千个朋友,那么您将使用第一个方案,并执行更多写入而不是更多查询,因为您可以在用户上传后在后台执行写操作,但查询必须发生用户在等待。

作为非规范化的一个例子,看一下在单个click occurs时twitter rainbird的写入次数。每次写入都用于支持单个查询。

答案 1 :(得分:1)

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

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

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

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

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

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

迪安

答案 2 :(得分: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 对于您描述的项目类型,这是一个很好的优化技术集合。