HBase模式案例:客戶/訂單

2018-03-26 13:39 更新

HBase案例:客戶/訂單

假設 HBase 用于存儲客戶和訂單信息。有兩種核心記錄類型被攝取:客戶記錄類型和訂單記錄類型。

客戶記錄類型將包含您通常期望的所有內容:

  • 客戶編號
  • 客戶名稱
  • 地址(例如,城市,州,郵編)
  • 電話號碼等

訂單記錄類型將包含如下內容:

  • 客戶編號
  • 訂單編號
  • 銷售日期
  • 一系列用于裝運位置和訂單項的嵌套對象

假設客戶編號和銷售訂單的組合唯一地標識一個訂單,對于一個訂單(ORDER)表,這兩個屬性將組成 rowkey,特別是一個組合鍵,例如:

[customer number][order number]

但是,還有更多的設計決策需要:原始值是 rowkeys 的最佳選擇嗎?

Log Data 用例中的相同設計問題在這里面對我們??蛻艟幪柕拿荑€空間是什么,以及格式是什么(例如,數(shù)字或是字母數(shù)字?)由于在HBase中使用固定長度的密鑰以及可以在密鑰空間中支持合理分布的密鑰是有利的,因此會出現(xiàn)類似的選項:

帶有哈希的復合 Rowkey:

  • [客戶號碼的 MD5] = 16字節(jié)
  • [訂單號的 MD5] = 16字節(jié)

復合數(shù)字/哈希組合 Rowkey:

  • [代替客戶編號] = 8個字節(jié)
  • [訂單號的 MD5] = 16字節(jié)

單個表/多個表

傳統(tǒng)的設計方法會為有單獨的 CUSTOMER 和 SALES 表格。另一種選擇是將多個記錄類型打包到一個表中(例如,CUSTOMER ++)。

客戶記錄類型 Rowkey:

  • [customer-id]
  • [type] = 表示客戶記錄類型為'1'的類型

訂單記錄類型Rowkey:

  • [customer-id]
  • [type] = 指示訂單記錄類型為'2'的類型
  • [order]

這種特殊的 CUSTOMER ++ 方法的優(yōu)點是通過客戶 ID 來組織許多不同的記錄類型(例如,一次掃描就可以得到關于該客戶的所有信息)。缺點是掃描特定的記錄類型并不容易。

HBase訂單對象設計

現(xiàn)在我們需要解決如何建模 Order 對象。假設類結構如下:

Order

Order 可以有多個 ShippingLocations

LineItem

一個 ShippingLocation 可以有多個 LineItems

存儲這些數(shù)據(jù)有多種選擇。

完全標準化

通過這種方法,ORDER,SHIPPING_LOCATION和LINE_ITEM 將會有單獨的表格。

上面描述了 ORDER 表的 rowkey:schema.casestudies.custorder

SHIPPING_LOCATION 的復合 rowkey 就像這樣:

  • [order-rowkey]
  • [shipping location number] (例如,第一地點,第二地點等)

LINE_ITEM 表的復合 rowkey 將如下所示:

  • [order-rowkey]
  • [shipping location number] (例如,第一地點,第二地點等)
  • [line item number] (例如,第一條線,第二條等)

這樣的標準化模型很可能是 RDBMS 的方法,但這不是 HBase 唯一的選擇。這種做法的缺點是要檢索任何訂單的信息,您需要:

  • 獲取訂單的訂單表
  • 在 SHIPPING_LOCATION 表上掃描該訂單以獲取 ShippingLocation 實例
  • 掃描每個 ShippingLocation 的 LINE_ITEM

這是一個 RDBMS 無論如何都會在封面下做的事情,但由于 HBase 中沒有加入,所以您只是更加意識到這一點。

具有記錄類型的單個表

采用這種方法,將會存在一個包含單個表的ORDER

Order rowkey 如上所述:schema.casestudies.custorder

  • [order-rowkey]
  • [ORDER record type]

ShippingLocation 復合 rowkey 將如下所示:

  • [order-rowkey]
  • [SHIPPING record type]
  • [shipping location number] (例如,第一地點,第二地點等)

LineItem 復合 rowkey 將如下所示:

  • [order-rowkey]
  • [LINE record type]
  • [shipping location number] (例如,第一地點,第二地點等)
  • [line item number] (例如,第一條線,第二條等)

非規(guī)范化

具有記錄類型的單個表格的一種變體是對一些對象層次結構進行非規(guī)范化和扁平化,比如將 ShippingLocation 屬性折疊到每個 LineItem 實例上。

LineItem 復合 rowkey 將如下所示:

  • [order-rowkey]
  • [LINE record type]
  • [line item number] (例如,第一條線,第二條等,必須注意的是,在整個訂單中都是唯一的)

LineItem 列將是這樣的:

  • 項目編號(itemNumber)
  • 數(shù)量(quantity)
  • 價錢(price)
  • shipToLine1(從 ShippingLocation 非正規(guī)化)
  • shipToLine2(從 ShippingLocation 非正規(guī)化)
  • shipToCity(從 ShippingLocation 非正規(guī)化)
  • shipToState(從 ShippingLocation 非正規(guī)化)
  • shipToZip(從 ShippingLocation 非正規(guī)化)

這種方法的優(yōu)點包括不太復雜的對象層次結構,但其中一個缺點是,如果這些信息發(fā)生變化,更新會變得更加復雜。

BLOB對象

通過這種方法,整個 Order 對象圖都以某種方式處理為 BLOB。例如,上面描述了 ORDER 表的 rowkey:schema.casestudies.custorder,而一個名為“order”的列將包含一個可以反序列化的對象,該對象包含一個容器 Order,ShippingLocations 和 LineItems。

這里有很多選項:JSON,XML,Java 序列化,Avro,Hadoop Writable等等。所有這些都是相同方法的變體:將對象圖編碼為字節(jié)數(shù)組。應該注意這種方法,以確保在對象模型發(fā)生更改時保持向后兼容性,使舊的持久結構仍能從 HBase 中讀出。

優(yōu)點是能夠以最少的 I/O 來管理復雜的對象圖(例如,在本例中每個 HBase Get 有 Order),但缺點包括前面提到的關于序列化的向后兼容性,序列化的語言依賴性(例如 Java 序列化只適用于 Java 客戶端),事實上你必須反序列化整個對象才能獲得 BLOB 中的任何信息,以及像 Hive 這樣的框架難以使用像這樣的自定義對象。

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號