SuperColumn TMD到底是什么?Cassandra数据模型介绍
(一)
Translated by leo zheng
原文地址:WTF is a SuperColumn? An Intro to the Cassandra Data Model By Arin Sarkissian Digg
过去一两个月,Digg的工程师团队花费了大量时间研究、尝试Cassandra,并最终部署在生产环境。这是一个使用起来非常有趣的项目 —— 但是在享受乐趣之前,我们不得不花些时间搞清楚Cassandra的数据模型… “SuperColum TMD到底是什么”这句话被说了太多遍
如果你有关系型数据库的背景(几乎每个人都有),当学习Cassandra的数据模型时,你很可能会被一些命名规范困扰。我以及我在Digg的同事花了好 几天的时间讨论才真正弄明白。最近几周,有一封bikeshed(译注:指容易引起争论的、很难达成共识的话题)的邮件出现在开发者邮件列表里,建议使用 全新的命名方案以减少混乱。在整个讨论过程中,我一直在想:“可能用一些适当的例子可以减少人们对这些命名的困惑。” 因此,这就是我写此文来解释Cassandra数据模型的原因;它旨在帮助你从实例中学习,并不会深入每一个细节,但是,我还是希望它有助于你弄清一些东 西。
BTW:这篇文章比较长,如果你想要PDF版本,可以在这儿 下载。
各组成部分
在弄明白各个组成部分是如何组织在一起之前,让我们先一一认识它们:
Column
Column是数据增量最底层(也就是最小)的部分。它是一个包含名称(name)、值(value)和时间戳(timestamp)的三重元组。
下面是一个用JSON格式表示的column:
{ // 这是一个Column name: "emailAddress", value: "arin@example.com", timestamp: 123456789 }
就是这样。简洁起见,让我们忽略时间戳,只把它看作一个name/value的对。
另外,需要注意的是,name和value都是二进制的(技术上指byte[]),并且可以是任意长度。
SuperColumn
SuperColumn是指这样一个元组:包含一个二进制的name,value为可以包含无限数量的Column的map —— 使用Column的name作为key。仍然以JSON格式为例:
{ // 这是一个SuperColumn name: "homeAddress", // 无限数量的Column value: { // 注意,key就是Column的name street: {name: "street", value: "1234 x street", timestamp: 123456789}, city: {name: "city", value: "san francisco", timestamp: 123456789}, zip: {name: "zip", value: "94107", timestamp: 123456789}, } }
Column vs SuperColumn
Column和SuperColumn都是拥有name、value的元组。最大的不同在于标准Column的value是一个“字符串”,而 SuperColumn的value是一个包含多个Column的map。这是主要的区别。。。它们的value包含的是不同类型的数据。另一个细微的差 别是:SuperColumn没有时间戳。
继续前进之前
在继续前进之前,我希望通过一些方式来简化我们的示例:1)从Column中去除时间戳 2)将Column和SuperColumn的名称移到外面,这样看上去像一个key/value对。于是我们从:
{ // 这是一个SuperColumn name: "homeAddress", // 无限数量的Column value: { street: {name: "street", value: "1234 x street", timestamp: 123456789}, city: {name: "city", value: "san francisco", timestamp: 123456789}, zip: {name: "zip", value: "94107", timestamp: 123456789}, }
得到
homeAddress: { street: "1234 x street", city: "san francisco", zip: "94107", }
分组
有一个简单的结构用来分组Column和SuperColumn。。。这个结构被称作ColumnFamily,并且拥有两种形式:标准的&超级的
ColumnFamily
ColumnFamily是一种可以包含无限数量的行(row)的结构。哈哈,你是说行吗?是的 —— 就是行 :) 为了让你更好的理解,把它(译注:ColumnFamily)想象成关系型数据库中的表。
好的 —— 每一行拥有一个由客户端提供的(也就是你)key,以及一个包含多个Column的map。再强调一次,map中的key是Column的name,value是Column本身:
UserProfile = { // 这是一个ColumnFamily phatduckk: { // 这是ColumnFamily中这一行的key // 这一行中无限数量的Column username: "phatduckk", email: "phatduckk@example.com", phone: "(900) 976-6666" }, // 这一行结束 ieure: { // 这是ColumnFamily中另一行的key // 另一行中无限数量的Column username: "ieure", email: "ieure@example.com", phone: "(888) 555-1212" age: "66", gender: "undecided" }, }
记住:简单起见,我们只显示了Column的value,但事实上map中的value应该是整个Column。
你可以把它想象成HashMap/字典或关联数组( HashMap/dictionary or associative array)。如果你开始这么想了,那么你就走上正轨了。
需要指出的是:ColumnFamily没有固定模式(schema)。并没有预先定义行包含了哪些Column。在我们上面的示例中,你看到key是 “ieure”的行包含name为“age”和“gender”的Column,然而key是“phatduckk”的行并没有这两个Column。这是 100%灵活的:一个行可能包含1989个Column,而另一行只包含2个Column。一个行可能包含一个称作“foo”的Column,而其它的行 并没有。这就是Cassandra无模式的表现( This is the schemaless aspect of Cassandra)。
ColumnFamily也可以是超级的
现在,ColumnFamily可以有两种类型:标准的 或 超级的
我们刚才看到的示例是标准类型的ColumnFamily。标准类型的ColumnFamily是指所有的行包含的都是标准Column(即不是SuperColumn)的map。。。其中没有SuperColumn。
相反的,一个超级类型的ColumnFamily是指:每一行包含的是SuperColumn的map。这个map用SuperColumn的name作 为key,value是SuperColumn本身。并且,清楚起见,超级类型的ColumnFamily中不包含标准类型的ColumnFamily。 这儿是一个示例:
AddressBook = { // 这是一个超级类型的ColumnFamily phatduckk: { // 这是Super ColumnFamily中这一行的key // 这儿的key是地址簿所属人的名字 // 这一行中可以包含无限数量的SuperColumn // 该行内(译注:每一行包含的是一个map)的key是SuperColumn的名称 // 每一个SuperColumn是一个地址簿的条目 friend1: {street: "8th street", zip: "90210", city: "Beverley Hills", state: "CA"}, // 这是phatduckk的地址簿中被称作John的条目 John: {street: "Howard street", zip: "94404", city: "FC", state: "CA"}, Kim: {street: "X street", zip: "87876", city: "Balls", state: "VA"}, Tod: {street: "Jerry street", zip: "54556", city: "Cartoon", state: "CO"}, Bob: {street: "Q Blvd", zip: "24252", city: "Nowhere", state: "MN"}, ... // 我们可以拥有无限数量的SuperColumn (即地址簿条目) }, // 这一行结束 ieure: { // 这是Super ColumnFamily中另一行的key // ieure的地址簿的所有条目 joey: {street: "A ave", zip: "55485", city: "Hell", state: "NV"}, William: {street: "Armpit Dr", zip: "93301", city: "Bakersfield", state: "CA"}, }, }
Keyspace
Keyspace是数据分组的最外层。所有的ColumnFamily都包含在Keyspace当中。Keyspace常常用项目工程名称来命名。
Keyspace可以包含多个ColumnFamily,但这并不意味着它们之间有必然的关系(imposed relationship)。例如:这并不像MySQL中的table。。。你不能对它们做关联(join)。这是因为假设ColumnFamily_1 有一个key为“phatduckk”的行,并不意味着ColumnFamily_2也有key为“phatduckk”的行。