Understanding HBase and BigTable 譯文

weixin_33763244發表於2019-02-27

有時間翻譯一下這篇文章。http://jimbojw.com/#understan...

Google BigTable論文可下載:https://ai.google/research/pu...

在學習HBase(Google BigTable 的開源實現)的時候,我們面臨的最為困難的部分就是你需要重構你的思路來理解BigTable的概念。

非常不幸的是,在BigTable和HBase名稱中出現的table和base這兩個單詞,很容易讓我們與RDBMS(關係型資料庫管理系統)中的概念相混淆。

本文旨在從概念維度去描述清楚分散式資料儲存系統的含義。我們希望在讀完這篇文章之後,你能夠更有經驗去決定你到底需要的是HBase還是一個傳統資料庫系統。

術語

幸運的是,在論文Google's BigTable Paper中已經清晰的解釋了BigTable是什麼。在Data Model章節的第一句話是:

BigTable是一種稀疏的、分散式的、持久化的多維有序字典。

論文繼續解釋到:

BigTable由索引行、索引列以及時間戳組成,在字典中的每個值都是無解釋的位元組陣列。

在Hadoop wiki的HBaseArchitecture頁面中指出:

HBase使用了一種與Bigtable非常相似的資料模型。使用者在標記表中儲存資料行,資料行中有一個有序的key和任意數量的列。這張表的儲存是稀疏的,所以如果使用者喜歡的話,甚至可以在同一張表的每行中瘋狂的儲存差異巨大的列。

上面提到的這些概念似乎很神祕,但其實如果你要是想明白的話這些說法都是有道理的。下面我們就按照順序討論一下幾個主題:字典、持久化、分散式、有序、多維和稀疏。

相比起試圖直接描述一個完成的系統框架,我覺得描述清楚構建系統框架的核心要素更加容易理解。

字典

HBase 和 BigTable的核心是字典。根據你所使用的程式語言背景,你可能更加熟悉與之類似的詞語是陣列(PHP)、字典(Python)、雜湊表(Ruby)和物件(JavaScript)。

維基百科對字典的定義是:由一組關鍵字和值組成的抽象資料型別,其中每個關鍵字都關聯一個值。

使用JavaScript Object Notation語法,簡單的欄位示意如下所示:

{
    "zzzzz" : "woot",
    "xyz" : "hello",
    "aaaab" : "world",
    "1" : "x",
    "aaaaa" : "y"
}

持久化

持久化意思是說新增到字典中的資料在系統建立或處理完成後永遠存在,這個概念和其他各種持久化儲存系統並無不同,比如存放在檔案系統中的檔案一樣。

分散式

HBase 和 BigTable 構建在分散式檔案系統之上以便底層檔案儲存能夠在獨立機器陣列中分佈儲存。

HBase能夠構建在Hadoop's Distributed File System (HDFS)或者Amazon的Simple Storage Service (S3)上,而BigTable能夠在Google File System (GFS)中使用。

資料以一種類似於RAID系統的方式在多個參與節點中進行復制。

本文的目標並不關心分散式系統的實現方式,本文要說明的重點是HBase和BigTable是分散式的,提供了一個保護層,如叢集中某一節點故障。

有序

不像大多數字典的實現,在HBase/BigTable中鍵值對保持嚴格的字典序。即關鍵字『aaaaa』之後緊挨著『aaaab』,並且與『zzzzz』距離很遠。

考慮我們之前的例子,有序的版本看起來是這樣的:

{
    "1" : "x",
    "aaaaa" : "y",
    "aaaab" : "world",
    "xyz" : "hello",
    "zzzzz" : "woot"
}

​由於這些系統常常非常巨大而且是分散式的,有序特徵實際上非常重要。相似的關鍵字的行緊密相鄰,當你必須對錶進行掃描時,你最感興趣的條目之間彼此相鄰。

那麼,選擇什麼樣的行關鍵字就顯得十分重要。舉個例子,考慮一個表的關鍵字是主機名,那麼最好的辦法就是使用主機名的逆序列出他們,例如使用com.jimbojw.www而不是www.jimbojw.com,以便相同子域的那些行都與父域名稱相鄰。

繼續域名的例子,域名為mail.jimbojw.com的行將與名稱為www.jimbojw.com的行緊鄰,而不是mail.xyz.com。

在HBase/BigTable中的有序並不意味著值是有序的。除了關鍵字外並沒有任何自動的索引方式,這裡的實現就和舊有的字典實現一樣。

多維

到目前為止,我們還沒有提到任何有關『列』的概念,處理『表』,而不是普通意義上的雜湊表。『列』這個詞也像是『table』和『base』的概念一樣,承載了太多的RDBMS的情感在內。

代替的,我們可以把它理解為一個多維字典——即字典中巢狀字典。在上面JSON示例中增加一維:

{
    "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"  
        }
}

​在上面的例子裡,你注意到每個key都指向含有兩個key:A和B的字典。從這裡開始,我們將頂級的鍵值對稱之為行。在BigTable/HBase概念中,A和B被稱之為『列簇』。

表建立時列簇即被指定,之後不可能或者很難被修改。增加新的列簇也十分昂貴,因此最為明智的做法是在最開始就指定好列簇。

幸運的是,列簇可以有任意列,由『識別符號』或『標籤』指定。下面是JSON示例的子集,其中包含列識別符號:

{
// ...  
    "aaaaa" : {
        "A" : {
            "foo" : "y",
            "bar" : "d"
            },
        "B" : {
            "" : "w"
            }
    },
    "aaaab" : {
        "A" : {
            "foo" : "world",
            "bar" : "domination"
            },
        "B" : {
            "" : "ocean"
            }  
    },
// ...
}

​注意表示的兩個行,A列簇有兩個列:foo和bar,B列簇僅有一個列,它的識別符號是空字元。

當向HBase/BigTable查詢資料時,你必須提供全部列名,形式為:family:qualifier。對於這個例子,以上例子有三個列子:A:foo,A:bar和B:。

注意,儘管列簇是靜態的,列本身不是,考慮下面展開的行:

{
// ...
    "zzzzz" : {
        "A" : {
            "catch_phrase" : "woot",
            }
    }
}

​在這個示例中,行zzzzz有一列『A:catch_phrase』。由於每一行都有任意數目不同的列,沒有內建的方式查詢所有行中的所有列的列表。為了獲得資訊,你需要做一次全表掃描。但是你可以查詢所有列簇的列表,因為他們是不可變的。

在HBase/BigTable中的最後一維是時間。所有資料要麼使用整型時間戳,要麼使用自定義的整型資料去標識版本。客戶端在插入資料時可以指定時間戳。

使用任意整型時間戳的例子:

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

​每個列簇都有自己的規則規定了一個單元格最多能有多少個版本,在不給定時間戳的情況下,應用將請求被給定單元格資料。通常情況下,HBase/BigTable將返回最近的版本(即時間戳的值最大),因為它是按照時間逆序儲存的。

如果應用程式請求給定時間戳的給定行,HBase將返回時間戳等於或小於給定時間戳的單元格資料。

使用我們想象的HBase表,請求"aaaaa"/"A:foo"返回"y",請求"aaaaa"/"A:foo"/10返回"m",請求"aaaaa"/"A:foo"/2返回空結果。

稀疏

最後一點是稀疏。上面提到過了,在每個列簇中可以有任意數量的列,或者沒有。另一種型別的稀疏是基於行的間隙,這僅僅意味著鍵之間可能存在間隙。

當然,如果你以HBase/BigTable中基於字典的概念考慮的話就很好理解,而非RDBMS中相似的概念。

結語

希望本文能夠幫助你從概念上理解HBase資料模型感覺是什麼。

就像總結說的一樣,我期待著你的想法、評論和建議。

圖片描述

相關文章