1. 程式人生 > >HBase (2)---資料儲存結構

HBase (2)---資料儲存結構

在本文中的HBase術語:
基於列:column-oriented
行:row
列組:column families
列:column
單元:cell

理解HBase(一個開源的Google的BigTable實際應用)最大的困難是HBase的資料結構概念究竟是什麼?首先HBase不同於一般的關係資料庫,它是一個適合於非結構化資料儲存的資料庫.另一個不同的是HBase基於列的而不是基於行的模式.

Google's BigTable論文 清楚地解釋了什麼是BigTable:
Bigtable是一個疏鬆的分散式的持久的多維排序的map,這個map被行鍵,列鍵,和時間戳索引.每一個值都是連續的byte陣列.(A Bigtable is a sparse, distributed, persistent multidimensional sorted map. The map is indexed by a row key, column key, and a timestamp; each value in the map is an uninterpreted array of bytes.)

Hadoop wiki的HBase架構 頁面提到:
HBase使用和Bigtable非常相同的資料模型.使用者儲存資料行在一個表裡.一個數據行擁有一個可選擇的鍵和任意數量的列.表是疏鬆的儲存的,因此 使用者可以給行定義各種不同的列.(HBase uses a data model very similar to that of Bigtable. Users store data rows in labelled tables. A data row has a sortable key and an arbitrary number of columns. The table is stored sparsely, so that rows in the same table can have crazily-varying columns, if the user likes.)

實質上,HBase和BigTable是個map.相同於陣列(PHP),詞典(Pyhton),Hash(Ruby)或者Object (Javascript)中的表現形式.所以每一行是一個map,這個map中還可以有多個map(基於列組).獲取一個數據就像你從map中獲取資料一 樣.給定一個行名(即從這個map中獲取資料),然後給定一個key(列組名+限定詞)來取得資料.

HBase 和BigTable都是在分散式檔案系統上構建的,所以基礎的檔案儲存能夠散佈在分散式檔案系統的機器上.
HBase使用Hadoop's Distributed File System(HDFS) 或 Amazon's Simple Storage Service(S3),Kosmos Distributed File System(KFS), 與此一樣BigTable使用Google File System(GFS).資料被複制到多個節點就像資料被儲存在一個RAID系統上.

不像大多數的map應用,在HBase和BigTable中,key/value 是非常嚴格地按字母次序排列的.那就是意味著鍵值為"aaaaa"的行下一個行的鍵值為"aaaab",但是和鍵值為"zzzzz"的行離的很遠.因為這 些系統都是非常龐大和分散式的, 這些特性是非常重要的. 空間接近的列保證當你確定要瀏覽表時, 你感興趣的行將會靠近這行.當你選擇行的鍵值時,這是非常重要的事情.例子:考慮你表中的列是域名.最好是倒過來的(因此 "com.jimbojw.www"比"www.jimbojw.com"更好) ,因為你的子域名將會靠近你的主域名.注意在HBase中排序僅僅是kay排序,value是不排序的.

在下面的JSON資料中,我們看到整個資料結構是一個map,並且map中每一個key對應一個包含 "A"和"B"的map.假設整個下面資料是一個table,那麼它有"1"."aaaaa","aaaab","xyz","zzzzz"這幾個行,每 一個行有一個"A"和"B"的map.在HBase的術語中, 稱"A"和"B"為列組.

{
  "1" : {
    "A" : "x",
    "B" : "z"
  },
  "aaaaa" : {
    "A" : "y",
    "B" : "w"
  },
  "aaaab" : {
    "A" : "world",
    "B" : "ocean"
  },
  "xyz" : {
    "A" : "hello",
    "B" : "there"
  },
  "zzzzz" : {
    "A" : "woot",
    "B" : "1337"
  }
}

在HBase中一個列組通過限定詞或叫做標籤使每一個列組能夠包含許多的列.

{
  "aaaaa" : {
    "A" : {
      "foo" : "y",
      "bar" : "d"
    },
    "B" : {
      "" : "w"
    }
  },
  "aaaab" : {
    "A" : {
      "foo" : "world",
      "bar" : "domination"
    },
    "B" : {
      "" : "ocean"
    }
  },
  "zzzzz" : {
    "A" : {
      "catch_phrase" : "woot",
    }
    "B" : {
      "" : "1337"
    }
  }
}

在上面的例子中,在"aaaaa"的行中,列組"A"包含兩個列:"foo"和"bar",列組"B"僅僅有一個限定詞為空字元竄""的列.當我們 向HBase獲取資料時,你必須提供完整的列名字"<列組>:<限定詞>".因此上面的例子中行"aaaaa"和"aaaab" 都包含三個列:"A:foo", "A:bar"和"B:".儘管在行中列組是固定的,但是同一個列中限定詞可以是不同的,就像行"zzzzz"中列組"A"中只有一個列 "catch_phrase".最後的維度是時間戳(timestamp).所有的在HBase中儲存的資料都有一個用時間戳表示的版本或者你自己通過指 定時間戳來插入或獲取資料.

{
  "aaaaa" : {
    "A" : {
       "foo" : {
        15 : "y",
        4 : "m"
      },
      "bar" : {
        15 : "d",
      }
    },
    "B" : {
      "" : {
        6 : "w"
        3 : "o"
        1 : "w"
      }
    }
  }
}

每一個列可以指定多少版本的資料被儲存在每一個單元.在上面的例子中行"aaaaa"的列"A:foo"包含兩個倒序時間戳排列的資料15和4,列 "B"包含由三個倒序時間戳排列的資料.一般的應用程式只是簡單(不通過時間戳)的請求一個單元的資料.在這種條件下,HBase只是簡單地返回最新的版 本,即時間戳最大的版本.要獲取"A:foo"返回"y",要獲取"B"返回"w".如果應用程式在一個行中請求時帶上時間戳,HBase將會返回小於或 等於請求時間戳的資料.接著上面的例子如果程式請求"A:foo"帶上時間戳10,返回"m",加上時間戳3,返回null.

每一個行可以多個列族,每一個列族可以包含無數個列,每一個列都可以有一個不同於其他列的時間戳.在通用資料庫中當表建立時我們就已經定義了列,如果修改表結構的話會非常困難(比如:新增一列).在HBase中我們可以很輕鬆地新增一個列族或列.