SuperColumn TMD到底是什么?Cassandra数据模型介绍(二)

SuperColumn TMD到底是什么?Cassandra数据模型介绍

(二)

Translated by leo zheng

原文地址:WTF is a SuperColumn? An Intro to the Cassandra Data Model   By  Arin Sarkissian Digg

 

排序(Sorting)

        OK - 我们已经了解了各种数据容器(data containers),数据模型另一个重要的组件是:数据是如何排序的。Cassandra并不同于SQL的查询( Cassandra is not queryable like SQL)- 当你获取数据的时候你不会指定你想要的数据排序方式(还有其它区别)。数据在你将它们放入集群的时候就已经排好序了,并且一直保持排序!这极大的提高了读 取时的性能,然而为了获得这个好处,你必须按照能够满足你的数据访问模式的方式来设计数据模型。

        Columns总是按照name在它们所属的行中来排序的。这非常重要,因此我要再强调一遍:Columns总是按照它们的name来排序!name是如 何比较的,这取决于ColumnFamilys的CompareWith选项。(Cassandra)提供了以下一些选项:BytesType, UTF8Type, LexicalUUIDType, TimeUUIDType, AsciiType, 以及 LongType。每一个选项将Column的name看作是不同的数据类型,你可以灵活选择。例如:使用LongType,Column的name就被 看作是64位的长整型。为了更好的理解,让我们来看一些数据排序前后的情况:

// 这儿展示了一行中所有column随机排序时的情况
// 这仅仅是一个示例,Cassandra存储数据绝对不会随机排序
// 同时,忽略(Column的)值 - 它们和排序无关
    {name: 123, value: "hello there"},
    {name: 832416, value: "kjjkbcjkcbbd"},
    {name: 3, value: "101010101010"},
    {name: 976, value: "kjjkbcjkcbbd"}

        由于我们使用LongType选项,因此,这些Column的排序会是这样:

<!--
    storage-conf.xml中定义的ColumnFamily
-->
    <ColumnFamily CompareWith="LongType" Name="CF_NAME_HERE"/>
    // 看到了吗,Column的name被看作是64位长整型了
    // 事实上,Column的name按照数值大小排序了
    {name: 3, value: "101010101010"},
    {name: 123, value: "hello there"},
    {name: 976, value: "kjjkbcjkcbbd"},
    {name: 832416, value: "kjjkbcjkcbbd"}

        你可以看到,Column的name是按照64位长整型(这样可以是非常大的数字)进行比较的。
现在,如果我们用CompareWith的另一个选项,我们将会得到不同的结果。我们把CompareWith设置为UTF8Type,这样Column的name将被看作是UTF8类型,因此,排序的结果将会是这样:

<!--
    storage-conf.xml中定义的ColumnFamily
--> 
<ColumnFamily CompareWith="UTF8Type" Name="CF_NAME_HERE"/>
    // Column的name被看作是UTF8形式的字符串
    {name: 123, value: "hello there"},
    {name: 3, value: "101010101010"},
    {name: 832416, value: "kjjkbcjkcbbd"},

    {name: 976, value: "kjjkbcjkcbbd"}

        结果完全不同了!
        这样的排序原则同样也适用于SuperColums,只是我们额外有个维度需要处理:我们不仅要决定一行中各个SuperColumns如何排序,我们还 要决定每一个SuperColumn中各个Column如何排序。每个SuperColumn中各个Column的排序方式是由 CompareSubcolumnsWith指定的。这儿有个示例:

    // 这儿展示了一个拥有2个SuperColumn的行
    // 现在它们是随机排序的

    { // 该行中第一个SuperColumn
        name: "workAddress",
        // 其中的Columns
        value: {
            street: {name: "street", value: "1234 x street"},
            city: {name: "city", value: "san francisco"},
            zip: {name: "zip", value: "94107"}
        }
    },
    { // 同一行中另一个SuperColumn
        name: "homeAddress",
        // 其中的Columns
        value: {
            street: {name: "street", value: "1234 x street"},
            city: {name: "city", value: "san francisco"},
            zip: {name: "zip", value: "94107"}
        }
    }

        现在,如果我们把CompareSubcolumnsWith 和CompareWith 都设为UTF8Type,我们将得到如下的排序结果:

// 现在,已经排好序了
{
        // 由于将类型视为UTF8的字符串,所以 "homeAddress" 排在 "workAddress"之前
        {
            name: "homeAddress",
            // SuperColumn中的Columns同样按名称排序了
            value: {
                 // 看,它们也按照Column的名称排序了
               city: {name: "city", value: "san francisco"},
               street: {name: "street", value: "1234 x street"},
               zip: {name: "zip", value: "94107"}
            }
        },
       { // 同一行中的另一个SuperColumn
             name: "workAddress",
             value: {
                 // SuperColumn中的Columns同样按名称排序了
                city: {name: "city", value: "san francisco"},
                street: {name: "street", value: "1234 x street"},
                zip: {name: "zip", value: "94107"}
             } 
       }
}

        我想要指出的是:虽然上面的示例中CompareSubcolumnsWith 和 CompareWith 的值都被设置为UTF8Type,但这不是必须的。你可以根据需要为CompareSubcolumnsWith 和 CompareWith 设置不同的值。
关于排序我想要提及的最后一点是:你可以写一个自定义的类来进行排序。排序机制是可插拔的(pluggable)。。。你可以设置CompareSubcolumnsWith 和/或 CompareWith 的值为任意类的全路径名(fully-qualified class name),只要这个类实现了接口:org.apache.cassandra.db.marshal.IType(也就是说你可以自定义比较器(comparators))。

 

Schema示例(Example Schema)


        好的 —— 现在我们已经认识了难题(译注:指Cassandra数据模型)的各块内容,让我们把它们组合在一起,构造一个简单的Blog系统。我们将要构造的系统包含以下规则:
        * 支持单篇Blog
        * 可以有多个作者(authors)
        * Blog包含标题(title)、内容(body)、slug 和(发布日期)publish date
        * Blog可以和任意标签(tag)关联
        * 人们可以添加评论(comments ),但不能注册:他们每次都输入个人信息(这只是为了简单)
        * 评论包含内容(text)、提交时间(time submitted)、评论者的姓名(commenter’s name)
        * 必须能按时间倒序显示所有发布的Blog(最新的排在最前面)
        * 必须能按时间倒序显示某个tag相关的Blog
        下面的各个部分描述了我们系统的Keyspace里定义的ColumnFamily,展示了XML的定义、讨论了我们选择不同排序方式的原因,并且以JSON格式展示了ColumnFamily中的数据。

 

Authors ColumnFamily
        构造Authors ColumnFamily是非常简单的;没有任何花哨的东西。每一个Author就是一行,并且使用Author的全名(full name)作为Key。在每一行中,每一个Column表示的是Author的一个个人信息属性。

        这是一个用一行来表示一个对象的例子。。。这个case中是Author对象。这种方式下,每一个Column表示一个属性。超级简单。我要指出的是,由于没有任何的一行中必须包含哪些Column的定义,因此我们拥有了一个无模式(schemaless)的设计。
        我们将根据Key来访问各行,并且每一次查询总是获取所有的Column(我们永远不会通过Key —— 'foo',来获取这一行中的前三个Column)。这意味着我们并不关心Column是如何排序的。因此,我们使用BytesType 排序选项,因为它不需要对Column的name做任何验证。

<!--
    ColumnFamily: Authors
    我们在这存储所有的Author信息

    Row Key => Author的姓名(这意味着姓名必须是唯一的)
    Column Name: Author的一个属性(标题、内容等)(译注:应该是tiwtter账号、email等)
    Column Value: 属性的值
    访问: 通过姓名获取一个author(即获取某一行的所有Column)
    Authors : { // CF
        Arin Sarkissian : { // row key
            // Columns对应Author的各个属性
            numPosts: 11,
            twitter: phatduckk,
            email: [email protected],
            bio: "bla bla bla"
        },
        // 其他authors
        Author 2 {
            ...
        }
    }
-->
<ColumnFamily CompareWith="BytesType" Name="Authors"/>

 

BlogEntries ColumnFamily
        再说一遍,这个ColumnFamily只是用来做简单的key/value查询。每一篇blog存为一行。行中的每一个Column表示blog的一个属性:标题、内容等(和前面的例子一样)。一个小优化,我们把tag用逗号分隔的形式存入一个Column。这样,在显示的时候我们只需要分割这个Column的值,就可以得到一个tag列表。
        每一行的key是blog的slug。因此当我们想要获得一篇blog的时候,就可以简单的通过这个key(slug)来查询。

<!--
    ColumnFamily: BlogEntries
    所有的blog存放在这

    Row Key +> blog的slug (uri中为了搜索引擎优化的部分)
    Column Name: blog的一个属性 (标题、内容等)
    Column Value: 属性的值

访问: 通过slug获取一篇blog (通常是获取一行中的所有Column)

fyi: tags是反规范化的。。。它是一个用逗号分隔的列表。
我没有使用json格式是为了不影响我们的表示方法,当然,只要你的程序能够处理,你可以使用任何格式

BlogEntries : { // CF
        i-got-a-new-guitar : { // row key - blog的具有唯一性的slug
            title: This is a blog entry about my new, awesome guitar,
            body: this is a cool entry. etc etc yada yada
            author: Arin Sarkissian  // Authors CF中一行的key
            tags: life,guitar,music  // 逗号分隔的tags列表(反规范化的)
            pubDate: 1250558004      // 发布时间(unixtime)
            slug: i-got-a-new-guitar
        },
        // 其它的blog
        another-cool-guitar : {
            ...
            tags: guitar,
            slug: another-cool-guitar
        },
        scream-is-the-best-movie-ever : {
            ...
            tags: movie,horror,
            slug: scream-is-the-best-movie-ever
        }
    }
-->
<ColumnFamily CompareWith="BytesType" Name="BlogEntries"/>

你可能感兴趣的:(设计模式,sql,json,Blog,cassandra)