Cassandra 文件

版本

您正在檢視預發行版本的說明文件。

邏輯資料建模

現在您已定義查詢,可以開始設計 Cassandra 表格。首先,建立一個邏輯模型,其中包含每個查詢的表格,擷取概念模型中的實體和關係。

若要命名每個表格,您將識別您要查詢的主要實體類型,並使用它來開始實體名稱。如果您要透過其他相關實體的屬性進行查詢,請將它們附加到表格名稱中,並以by分隔。例如,hotels_by_poi

接下來,您識別表格的主鍵,根據所需的查詢屬性新增分割鍵欄位,並以群集欄位排序,以保證唯一性並支援所需的排序順序。

主鍵的設計非常重要,因為它將決定每個分割區中儲存多少資料,以及這些資料在磁碟上的組織方式,這反過來會影響 Cassandra 處理讀取的速度。

透過新增查詢識別的任何其他屬性,完成每個表格。如果這些其他屬性對於分割鍵的每個執行個體都相同,請將該欄位標記為靜態。

現在,這是對相當複雜的流程的相當快速的描述,因此值得深入探討一個詳細的範例。首先,讓我們介紹一個符號,您可以用它來表示邏輯模型。

Cassandra 社群中的多位個人提出了以圖表形式擷取資料模型的符號。本文檔使用 Artem Chebotko 推廣的符號,它提供了一個簡單且有資訊性的方式,用以視覺化設計中查詢和表格之間的關係。此圖顯示邏輯資料模型的 Chebotko 符號。

image

每個表格都顯示其標題和欄位清單。主鍵欄位透過符號識別,例如分割鍵欄位的K,以及表示群集欄位的C↑或C↓。顯示線條進入表格或表格之間,以指出每個表格設計為支援的查詢。

旅館邏輯資料模型

下圖顯示一個 Chebotko 邏輯資料模型,用於查詢涉及飯店、景點、房間和便利設施。您會立即注意到,Cassandra 設計中不包含專用的房間或便利設施表格,就像您在關係設計中所做的那樣。這是因為工作流程未識別需要此直接存取的任何查詢。

image

讓我們探討這些表格的每個詳細資料。

第一個查詢 Q1 是尋找景點附近的飯店,因此您會將此表格稱為 hotels_by_poi。依據命名的景點進行搜尋,表示景點應該是主鍵的一部分。讓我們依據名稱參照景點,因為根據工作流程,這是使用者將開始搜尋的方式。

您會注意到,在一個特定景點附近肯定會有多家飯店,因此您需要在主鍵中加入另一個組成部分,以確保每個飯店都有唯一的分割區。因此,您將飯店金鑰新增為叢集欄位。

在設計表格主鍵時,一個重要的考量是確保它定義一個唯一的資料元素。否則,您有意外覆寫資料的風險。

現在,對於第二個查詢 (Q2),您需要一個表格來取得特定飯店的資訊。一種方法是將飯店的所有屬性放入 hotels_by_poi 表格中,但您只新增應用程式工作流程所需的那些屬性。

從工作流程圖中,您知道 hotels_by_poi 表格用於顯示飯店清單,其中包含每家飯店的基本資訊,而應用程式知道傳回飯店的唯一識別碼。當使用者選擇一家飯店來檢視詳細資料時,您可以使用 Q2,它用於取得飯店的詳細資料。由於您已經從 Q1 取得 hotel_id,因此您可以將其用作您正在尋找的飯店的參考。因此,第二個表格只稱為 hotels

另一個選項是在飯店表格中儲存一組 poi_names。這是一種同樣有效的做法。您將透過經驗瞭解哪種做法最適合您的應用程式。

Q3 只是 Q1 的反向——尋找飯店附近的景點,而不是景點附近的飯店。然而,這次您需要存取每個景點的詳細資料,如 pois_by_hotel 表格所示。與先前相同,您將景點名稱新增為叢集金鑰以保證唯一性。

在這裡,我們現在考慮如何支援查詢 Q4,以協助使用者尋找他們有興趣入住的夜晚中,所選飯店的空房。請注意,此查詢包含開始日期和結束日期。由於您查詢的是一個範圍,而不是單一日期,因此您知道您需要將日期用作叢集鍵。使用 hotel_id 作為主鍵,將每個飯店的房間資料分組到單一分區中,這應有助於搜尋變得非常快速。我們稱之為 available_rooms_by_hotel_date 表格。

若要支援範圍搜尋,請使用 叢集欄位 <clustering-columns> 來儲存您需要在範圍查詢中存取的屬性。請記住,叢集欄位的順序很重要。

available_rooms_by_hotel_date 表格的設計是寬分區模式的一個範例。當討論支援類似模型的資料庫時,此模式有時稱為寬列模式,但從 Cassandra 的角度來看,寬分區是一個更準確的描述。此模式的精髓是將多個相關列分組在一個分區中,以便在單一查詢中快速存取分區中的多個列。

為了完善資料模型的購物部分,請新增 amenities_by_room 表格以支援 Q5。這將允許使用者查看在所需住宿日期中可用的其中一間房間的便利設施。

預訂邏輯資料模型

現在讓我們轉換方向,看看預訂查詢。此圖顯示預訂的邏輯資料模型。您會注意到這些表格表示非正規化的設計;相同的資料出現在多個表格中,具有不同的鍵。

image

為了滿足 Q6,reservations_by_guest 表格可用於按訪客姓名查詢預訂。您可以想像查詢 Q7 會在自助服務網站上的訪客代表或嘗試協助訪客的客服中心代理人代表下使用。由於訪客姓名可能不是唯一的,因此您在此處也將訪客 ID 包含為叢集欄位。

Q8 和 Q9 特別有助於提醒您建立查詢,以支援應用程式的各種利害關係人,不僅是客戶,還有員工,甚至可能是分析團隊、供應商等等。

飯店員工可能希望查看按日期排列的即將到來的預訂記錄,以深入了解飯店的表現,例如飯店客滿或未售出的日期。Q8 支援按日期檢索特定飯店的預訂。

最後,您建立一個 guests 表格。這提供了一個用於儲存訪客資訊的單一位置。在這種情況下,您指定訪客記錄的單獨唯一識別碼,因為訪客具有相同姓名並不少見。在許多組織中,客戶資料庫(例如 guests 表格)將是獨立客戶管理應用程式的一部分,這就是為什麼範例中省略了其他訪客存取模式。

模式和反模式

與其他類型的軟體設計一樣,Cassandra 中的資料建模有一些眾所周知的模式和反模式。您已經在這個飯店模型中使用了最常見的模式之一,即寬分區模式。

時間序列模式是廣泛分區模式的延伸。在此模式中,特定時間間隔的一系列測量值會儲存在廣泛分區中,其中測量時間會用作分區金鑰的一部分。此模式經常使用在商業分析、感測器資料管理和科學實驗等領域。

時間序列模式也可用於測量值以外的資料。考慮銀行應用程式的範例。您可以將每個客戶的餘額儲存在一行中,但當不同的客戶查看其餘額或進行交易時,這可能會導致大量的讀取和寫入競爭。您可能會想將交易包裝在寫入中,只是為了保護餘額不會錯誤更新。相反地,時間序列樣式的設計會將每個交易儲存為帶時間戳記的行,並將計算目前餘額的工作留給應用程式。

許多新使用者會陷入的一個設計陷阱是嘗試使用 Cassandra 作為佇列。佇列中的每個項目都儲存在廣泛分區中,並帶有時間戳記。項目會附加到佇列的結尾,並從前面讀取,在讀取後刪除。這是一個看似有吸引力的設計,特別是因為它與時間序列模式非常相似。此方法的問題在於已刪除的項目現在是 墓碑 <asynch-deletes>,Cassandra 必須掃描它們才能從佇列的前面讀取。隨著時間推移,越來越多的墓碑會開始降低讀取效能。

佇列反模式提醒我們,任何依賴刪除資料的設計都可能是一個效能不佳的設計。

材料改編自 Cassandra, The Definitive Guide。由 O’Reilly Media, Inc. 出版。版權所有 © 2020 Jeff Carpenter、Eben Hewitt。保留所有權利。經許可使用。