瞭解大規模的讀取與寫入

請參閱這份文件,在建構應用程式架構以實現高效能和可靠性時做出明智的決策。本文件包含進階 Cloud Firestore 主題。如果您才剛開始使用 Cloud Firestore,請改為參閱快速入門指南

Cloud Firestore 是可擴充的彈性資料庫,適用於 Firebase 和 Google Cloud 的行動裝置、網路和伺服器開發作業。讓您輕鬆開始使用 Cloud Firestore,並編寫內容豐富且功能強大的應用程式。

為確保應用程式能繼續維持與資料庫大小和流量增加,建議您先瞭解 Cloud Firestore 後端的讀取和寫入機制。您也必須瞭解讀取和寫入資料與儲存空間層的互動方式,以及可能影響效能的基礎限制。

開始建構應用程式之前,請參閱下列各節瞭解最佳做法。

瞭解高階元件

下圖顯示與 Cloud Firestore API 要求相關的高階元件。

高階元件

Cloud Firestore SDK 和用戶端程式庫

Cloud Firestore 支援適用於不同平台的 SDK 和用戶端程式庫。雖然應用程式可以直接向 Cloud Firestore API 發出 HTTP 和遠端程序呼叫 (RPC),但用戶端程式庫會提供抽象層,簡化 API 使用方式並實作最佳做法。也可能提供離線存取、快取等其他功能。

Google Front End (GFE)

這是所有 Google 雲端服務通用的基礎架構服務。GFE 會接受傳入的要求,並將要求轉送至相關的 Google 服務 (在此情況下為 Cloud Firestore 服務)。它也提供其他重要功能,包括防範阻斷服務攻擊。

Cloud Firestore 項服務

Cloud Firestore 服務會檢查 API 要求,包括驗證、授權、配額檢查和安全性規則,並管理交易。此 Cloud Firestore 服務包含與儲存層互動的儲存用戶端

Cloud Firestore」儲存空間層

Cloud Firestore 儲存層負責儲存資料和中繼資料,以及 Cloud Firestore 提供的關聯資料庫功能。以下各節說明資料在 Cloud Firestore 儲存層中的整理方式,以及系統的資源調度方式。瞭解資料整理方式有助於設計可擴充的資料模型,並進一步瞭解「Cloud Firestore」的最佳做法。

索引鍵範圍和分割

Cloud Firestore 是 NoSQL 文件資料庫。您可以將資料儲存在「文件」中,文件是以「集合」的階層分類。每份文件的集合階層和文件 ID 都會轉譯為單一索引鍵。文件會按照這個索引鍵,按字母順序儲存和按照字母順序儲存。我們使用「索引鍵範圍」一詞,是指按照字母順序排列的連續金鑰範圍。

一般 Cloud Firestore 資料庫過大,無法容納單一實體機器。在某些情況下,資料上的工作負載對單個機器無法處理。為了處理大型工作負載,Cloud Firestore 會將資料分區,然後儲存在多部機器或儲存伺服器中,再提供及提供。這些分區會在資料庫資料表的區塊中,以稱為分割的索引鍵範圍進行。

同步複製

請注意,系統一律會自動同步複製資料庫。資料分割的備用資源位於不同的可用區中,即使可用區無法存取,仍可持續使用。持續複製到分割的不同副本是由用於共識的 Paxos 演算法管理。系統會選擇每個分割的一個備用資源做為 Paxos 領導者,負責處理分割的寫入作業。同步複製功能讓您隨時都能從 Cloud Firestore 讀取最新版本的資料。

整體成果是一個可擴充且可用性高的系統,無論工作量繁重和規模過大,都能提供低延遲的讀取和寫入功能。

資料版面配置

Cloud Firestore 是無結構定義的文件資料庫。但是在內部,資料主要會在儲存空間層的兩個關聯資料庫式資料表中配置資料,如下所示:

  • 文件表格:文件會儲存在這個表格中。
  • 索引表格:如果索引項目可以有效取得結果,並依索引值排序,則會儲存在這個表格中。

下圖顯示以分割方式呈現 Cloud Firestore 資料庫的資料表可能的呈現方式。分割會在三個不同的可用區中複製,每個分段都有獲派的 Paxos 領導者。

資料版面配置

單一區域與多區域

建立資料庫時,您必須選取區域多區域

單一區域位置是特定的地理位置,例如 us-west1Cloud Firestore 資料庫的資料拆分,有備用資源位於所選區域內的不同可用區,如先前所述。

多區域位置是由一組定義的區域組成,用來儲存資料庫的備用資源。在 Cloud Firestore 的多區域部署項目中,兩個區域都有資料庫完整資料的完整備用資源。第三個區域具有見證備用資源,這項備用資源不會維護完整的資料,但會做複製作業。透過複製多個區域的資料,即便會遺失整個區域,也能寫入及讀取資料。

如要進一步瞭解單一區域的位置,請參閱 Cloud Firestore 位置

單一區域與多區域

瞭解 Cloud Firestore 中寫入的生命週期

Cloud Firestore 用戶端可透過建立、更新或刪除單一文件來寫入資料。寫入單一文件時,必須在儲存空間層一次更新文件及其相關索引項目。Cloud Firestore 也支援包含多次讀取和/或寫入一或多份文件的不可分割作業。

針對各種類型的寫入作業,Cloud Firestore 提供關聯資料庫的 ACID 屬性 (完整性、一致性、隔離性和耐用性)。Cloud Firestore 也提供「可序列化」,也就是說,所有交易會顯示為以序列順序執行。

寫入交易的高階步驟

Cloud Firestore 用戶端使用前述任一方法發出寫入或修訂交易時,內部作業會在儲存空間層中做為資料庫讀取/寫入交易執行。交易可讓 Cloud Firestore 提供前述的 ACID 屬性。

做為交易的第一個步驟,Cloud Firestore 會讀取現有文件,並判斷對「文件」資料表中的資料所做的變異。

這也包括對索引表進行必要的更新,如下所示:

  • 要加入文件的欄位需要在「索引」表格中對應的插入項目。
  • 如果要從文件中移除欄位,必須在「索引」表格中對應刪除欄位。
  • 正在文件中修改的欄位,需要刪除 (舊值) 和插入 (新值) 。

為了計算前述的異動,Cloud Firestore 會讀取專案的索引設定。索引設定會儲存專案索引的相關資訊。Cloud Firestore 使用兩種類型的索引:單一欄位與複合。如要進一步瞭解在 Cloud Firestore 中建立的索引,請參閱 Cloud Firestore 中的索引類型

計算變動後,Cloud Firestore 會在交易中收集這些結果,然後修訂。

瞭解儲存空間層中的寫入交易

如先前所述,在 Cloud Firestore 中寫入作業涉及儲存空間層中的讀取/寫入交易。視資料的版面配置而定,寫入作業可能涉及一或多個分割,如資料版面配置所述。

在下圖中,Cloud Firestore 資料庫共有八個分割 (標示為 1 到 8),透過單一可用區的三個不同儲存伺服器代管,每個分割都會複製到 3 個(以上) 不同的可用區。每個分段都有一個 Paxos 領導者,針對不同分割區,其分處可能不同。

<span class=Cloud Firestore 資料庫分割">

假設有一個 Cloud Firestore 資料庫含有 Restaurants 集合,如下所示:

餐廳集

Cloud Firestore 用戶端會透過更新 priceCategory 欄位的值,要求 Restaurant 集合中的文件進行下列變更。

變更為集合中的文件

下列高階步驟說明寫入過程中發生的情況:

  1. 建立讀寫交易。
  2. 從儲存空間圖層的「Documents」(文件) 資料表,讀取 Restaurants 集合中的 restaurant1 文件。
  3. 索引表格中讀取文件的索引。
  4. 計算要對資料執行的變異。這個例子中有五種異動:
    • M1:更新「Documents」資料表中的 restaurant1 資料列,反映 priceCategory 欄位的值變更。
    • M2 和 M3:刪除「索引」資料表中的 priceCategory 舊值資料列,以遞減及遞增的方式排序。
    • M4 和 M5:在索引資料表中插入 priceCategory 新值的資料列,依遞減和遞增順序排列。
  5. 修訂這些異動。

Cloud Firestore 服務中的儲存空間用戶端會查詢擁有待變更資料列索引鍵的分割。假設分割 3 使用 M1,而分割 6 放送 M2 至 M5。此為分散式交易,將所有這些分割視為參與者。參與者分割可能也包含在讀寫交易中較早讀取的任何其他分割。

下列步驟描述修訂後的修訂內容:

  1. 儲存空間用戶端會發出修訂版本。修訂版本包含 M1-M5 異動內容。
  2. 雙方將分割 3 和 6 分,即為此交易的參與者。其中一位參與者會選擇協調者,例如分割畫面 3。協調者的工作是確保所有參與者的交易能以不可分割的形式修訂或取消。
    • 這些分割作業的主導備用資源需由參與者和協調者完成。
  3. 每位參與者和協調者都會透過各自的備用資源執行 Paxos 演算法。
    • 領導者會使用備用資源執行 Paxos 演算法。如果大多數備用資源在回應領導者收到 ok to commit 回應,就會達成仲裁。
    • 接著,每位參與者在準備 (兩階段修訂) 的第一階段時,通知協調者。如果任何參與者無法修訂交易,整筆交易為 aborts
  4. 當協調員確定所有參與者 (包括自己) 做好準備後,就會將 accept 交易結果通知所有參與者 (兩階段修訂的第二階段)。在這個階段,每位參與者會將修訂的決定記錄至穩定的儲存空間,然後交易才會完成。
  5. 協調者會在 Cloud Firestore 中回應交易已修訂的儲存用戶端。協調者和所有參與者也會對資料套用變異。

修訂生命週期

Cloud Firestore 資料庫較小時,單一分割可能會擁有變異 M1 至 M5 中的所有鍵。在這種情況下,交易中只有一個參與者,不必進行前述的兩階段修訂,因此會加快寫入速度。

多區域寫入

在多區域部署中,將備用資源分散於各個區域可提升可用性,但會產生效能成本。不同區域的備用資源之間的通訊需要較長的往返時間。因此,與單一區域部署相比,Cloud Firestore 作業的基準延遲時間略微不同。

我們設定備用資源的方式,讓分割作業的領導地一律保留在主要區域中。主要區域是指流量從該區域傳入 Cloud Firestore 伺服器的區域。這項主管決策可減少 Cloud Firestore 中的儲存體用戶端與備用資源負責人 (或多重分割交易的協調員) 之間的通訊延遲。

每次寫入 Cloud Firestore 時,也都與 Cloud Firestore 中的即時引擎有些互動。如要進一步瞭解即時查詢,請參閱「大規模瞭解即時查詢」一文。

瞭解 Cloud Firestore 中讀取的生命週期

這個章節將介紹 Cloud Firestore 中的獨立非即時讀取。Cloud Firestore 伺服器會在內部於兩個主要階段處理大部分的查詢:

  1. 「索引」資料表的單一範圍掃描
  2. 根據先前的掃描結果,「Documents」(文件) 資料表中的點查詢
,瞭解如何調查及移除這項存取權。 某些查詢的處理速度或處理量可能會比較少 Cloud Firestore中的 (例如 IN 查詢)。

從儲存空間層讀取資料後,系統會在內部使用資料庫交易,確保讀取作業的一致性。不過,與用於寫入的交易不同,這些交易不會鎖定,而是選擇時間戳記,然後執行該時間戳記的所有讀取作業。因為這些物件不會取得鎖定,因此不會封鎖並行的讀寫交易。如要執行這筆交易,Cloud Firestore 中的儲存空間用戶端會指定時間戳記範圍,讓儲存空間層瞭解如何選擇讀取時間戳記。在 Cloud Firestore 中,儲存空間用戶端所選的時間戳記類型取決於讀取要求的讀取選項。

瞭解儲存空間層中的讀取交易

本節說明讀取的類型,以及讀取方式在 Cloud Firestore 儲存空間層中的處理方式。

強式讀取

根據預設,Cloud Firestore 讀取作業具有同步一致性。這種同步一致性是指 Cloud Firestore 讀取作業會傳回資料的最新版本,可反映到讀取開始之前修訂的所有寫入作業。

單一分割讀取

Cloud Firestore 中的儲存用戶端會查詢擁有待讀取資料列索引鍵的分割。假設需要從前的章節中讀取分割 3 的內容。用戶端會將讀取要求傳送至最近的備用資源,以縮短往返延遲時間。

目前,視所選的備用資源而定,可能會發生下列情況:

  • 讀取要求會傳送至主要備用資源 (可用區 A)。
    • 由於領導者一直處於最新狀態,因此讀取作業可直接繼續進行。
  • 讀取要求會傳送至非主要備用資源 (例如可用區 B)
    • 分割 3 可能會根據其內部狀態得知具有足夠資訊來處理讀取作業,而分割作業會如此。
    • 分割 3 不確定是否已看到最新的資料。它會傳送訊息給領導者,要求取得提供讀取作業所需的最後一筆交易的時間戳記。一旦套用交易,系統就會繼續讀取作業。

接著 Cloud Firestore 會將回應傳回用戶端。

多重分割讀取

如果需要從多個分割中完成讀取,所有分割都會使用相同的機制。從所有分割內容傳回資料後,Cloud Firestore 中的儲存體用戶端會合併結果。接著,Cloud Firestore 會使用這些資料回應用戶端。

過時讀取

強式讀取是 Cloud Firestore 的預設模式。不過,由於領導者可能需要進行通訊,延遲時間也可能比較長。一般來說,Cloud Firestore 應用程式不需要讀取最新版本的資料,且這項功能可以妥善處理幾秒鐘的過時資料。

在這種情況下,用戶端可能會使用 read_time 讀取選項,選擇接收過時的讀取。在這個範例中,讀取作業會在資料位於 read_time 時完成,而最近的備用資源很可能已確認在指定 read_time 有資料。 為獲得明顯更好的效能,合理的過時程度值是 15 秒。即使是過時讀取,產生的資料列也會保持一致。

避免使用無線基地台

Cloud Firestore 中的分割會自動拆分為較小的部分,在有需要或索引鍵空間展開時,將提供流量的工作分配給更多儲存空間伺服器。為因應多餘流量而建立的分割,即使流量離開流量,仍會保留大約 24 小時。因此,如果流量週期性攀升,分割程序會維持現有比例,並在需要時增加更多分配比例。這些機制有助於 Cloud Firestore 資料庫在流量負載或資料庫規模增加時,自動調度資源。但請留意下列幾項限制。

分割儲存空間和負載需要時間,如果流量速度過快,可能會導致延遲時間過長或超過期限錯誤 (在服務調整期間常稱為「熱點」)。最佳做法是將作業分散到索引鍵範圍,同時增加資料庫中集合的流量 (每秒 500 次操作)。逐步適應後,每五分鐘的流量最多可增加 50%。這個程序稱為 500/50/5 規則,並將資料庫定位為最適合您的工作負載擴充規模。

雖然 Cloud Firestore 會在負載增加時自動建立分割,但僅可使用一組專屬的複製儲存空間伺服器,在提供單一文件前分割索引鍵範圍。因此,在單一文件上持續進行大量並行作業,可能會導致該文件出現資源使用率不均的情形。如果單一文件的延遲時間持續過長,建議您考慮修改資料模型,藉此分割或複製多份文件的資料。

多項作業嘗試同時讀取及/或寫入同一份文件時,會發生爭用錯誤。

另一種特殊情況是,在 Cloud Firestore 中,依序增加/減少索引鍵的索引鍵會做為文件 ID,且每秒執行大量作業。流量激增的情況只會移到新建立的拆分,無法促成更多拆分。由於根據預設,Cloud Firestore 會自動為文件中的所有欄位建立索引,因此如果文件欄位含有依序增加/減少的值 (例如時間戳記),也可能會在索引空間上建立移動熱點。

請注意,按照上述做法,Cloud Firestore 可以調度資源來因應各種規模的工作負載,您不必調整任何設定。

疑難排解

Cloud Firestore 提供 Key Visualizer 做為診斷工具,專門用來分析使用模式並排解資源使用率不均的問題。

後續步驟