2014年8月13日 星期三

Google Cloud Datastore with Go 學習筆記 - Overview

Google Cloud Datastore with Go 學習筆記 - Overview

與傳統關聯式資料庫的差異

與傳統資料庫比較,Google Cloud Datastore(以下簡稱 Datastore) 架構於分散式系統上,擁有高度的可延展性,在裡面存放的資料以 Entity 的形式存在。
以下有幾項重要的不同:

  • Datastore 是以可延展為前提所設計,在繁忙工作時依然有高效能的表現

    • 寫入 Datastore 的資料會被自動分散到不同的機器上。
    • 讀取 Datastore 的資料時,假設查詢相同數量的資料(例如:50 個 Entity),不論是向擁有 100 個 Entityt 的 Dataset 查詢,或是向有 100 萬個 Entity 的 Dataset 查詢,都會是一樣的快速。
  • 因為所有的查詢都必須有預先定義好的 index 來處理,因此查詢語法的變化就無法像傳統關聯式資料庫一樣多變,以下類型的查詢就不支援:

    • Join
    • 多欄位的 not equal 篩選
    • 子查詢
  • 不同於關聯式資料庫,Table 中的每一筆資料的型態都要是相同的;在 Datastore 中,即使相同 kind 的 Entity 也不一定有要相同的屬性

Entity

存放於 Datastore 內的資料以物件(object)的形式存在,這些物件稱為 Entity

Entity 內可以有一或多個屬性,這些屬性稱為 Property

每個 Property 都會有其對應的 Value,這些 value 可以是各式不同的型態,包括整數、浮點數、字串
、日期、二進位資料 …. 等。

Datastore entity 是 schemaless 的,若是要確保每個 entity 都會有相同的 property set,就必須透過程式自行控制。

Kind / Key / Identifier

每個 entity 都屬於特定的 kind,目的是可以在之後進行有分類的查詢,例如:位於人事系統中的職員資料,可能就會屬於 Employee 這個 kind。

每個 entity 都有專屬且唯一的 key,而 key 是由以下項目所組成:

  • entity 所屬的 kind
  • Identifier,可能是一個 key name 字串,或是整數 ID
  • 若是以階層式存在的 entity,還會包含 ancestor path 資訊

因為 identifier 是屬於 entity key 的一部分,因此在 entity 建立時就會指派且無法變更,可以有兩種方式指派:

  1. 程式中直接指定 key name 字串給 entity
  2. 讓 Datastore 自動指定整數 ID 給 entity (有兩種產生整數 ID 的 policy,可參考文章1文章2)

Ancestor path

就像檔案系統一樣,entity 也可以以階層式的方式存放。(entity 中還包含了 child entity)

沒有 parent 的 entity 稱為 root entity

entity 之間的父子關係若是已經給定了就無法再更改,而 Datastore 不會指派相同的整數 ID 給同樣 parent 的 entity 或是兩個 root entity。

由於 entity 有父子關係,因此要完整表示一個 child entity 的 key,就必須包含類似以下的 ancestor path 資訊:

[Person:GreatGrandpa, Person:Grandpa, Person:Dad, Person:Me]

若是 root entity,ancestor path 資訊就大概會像下面這樣:

[Person:GreatGrandpa]

Query & Index

若想要對 Datastore 進行查詢,可以包含以下資訊:

  • 指定要查詢的 kind 資訊之外
  • 根據查詢需求指定 filter,而 filter 資訊可以是 entity 的 key / value / ancestor … 等資訊
  • 用來根據 property 來排序查詢結果用的 sort orders 資訊

查詢結果可以是完整的 entity 資訊,或是僅有部分 property 的 entity,也可以只有 entity key。

為了確保查詢效能,建議每個查詢都包含指定有限數量的 entity,避免一次回傳太多資料而影響查詢效能。

若是要確保回傳的資料達到 strong consistent 的狀態,在規劃資料存放的架構時,就要指定好相關的 entity 都放置於相同的 entity group 中,否則 Datastore 只能確保回傳的資料是 eventually consistent

App Engine 會預先在 entity 的每個 property 上定義 index,若要定義更複雜的 index 資訊,則可以修改 index.yaml 這個檔案。

Transaction

相同於傳統的關聯式資料庫,每一個交易可以包含多個 insert / update / delete 的操作,這些操作最多可以同時分布到 5 個不同的 entity group。

Datastore 使用 [optimistic concurrency] 的機制來管理 transaction,當多個交易同時針對相同的 entity group 進行修改時,只有第一個 transaction 的 commit 會成功,其餘會失敗,而失敗的 transaction 可以針對第一個 transaction 已經修改好的資料重新嘗試變更操作。也因為這種機制,就限制了對於相同的 entity group 可以同時進行的 transaction 數量。

同一個 transaction 中若是對多個 entity group 進行操作,就稱為 cross-group (XG) transaction,最多可以同時對 5 個 entity group 進行操作。

在 cross-group transaction 終無法執行 non-ancestor query,因為此類型的查詢可能會包含部分之前被 commit 後的交易結果。

而且在 cross-group transaction 中,即使只有讀取 entity group 的資料而未修改,但若有其他 transaction 同時存取相同的 entity group,也是會有衝突錯誤發生的。

Quotas and limits

使用 Google Cloud Datastore,有幾種不同的 quota 定義必須了解:

  • Datastore API Calls quota
    每次呼叫 Datastore API 的次數屬於此類 (有些 library 的一次呼叫會包含多次的 Datastore API Call)。

  • Data Send to Datastore API quota
    透過應用程式傳來的資料屬於此類。

  • Data Received from Datastore API quota
    應用程式接收到來自 Datastore 的資料屬於此類。

  • Stored Data quota
    存於 Datastore 的資料(包含 entity 的 property & key,甚至 index 都算)數量屬於此類。若要了解這些資料在 Datastore 中詳細的存放方式,可以參考 How Entities and Indexes Are Stored 這篇文章。

參考資料

  1. Go Datastore API - Go — Google Developers

沒有留言:

張貼留言