然而,維護(hù)多個(gè)副本數(shù)據(jù)會(huì)影響到數(shù)據(jù)插入和更新的性能,并會(huì)增加應(yīng)用程序的復(fù)雜性。因此,需要根據(jù)應(yīng)用程序指定的性能要求在讀取性能與數(shù)據(jù)維護(hù)成本之間做出權(quán)衡。
在這個(gè)階段要做出的另一個(gè)決定是要選擇使用聚集鍵還是多值類型來進(jìn)行數(shù)據(jù)推升。一般來說:
在只有一個(gè)子次要實(shí)體向上推升的情況下使用聚集鍵,特別是在子次要實(shí)體本身有子節(jié)點(diǎn)上卷的情況下。
在有多個(gè)子實(shí)體推升到主要實(shí)體的時(shí)候使用多值類型
請(qǐng)注意,這些規(guī)則可能比較簡單,但它們可以引申出對(duì)這方面更深入的思考。
第三階段:審核與調(diào)優(yōu)
最后一個(gè)階段則是在必要的情況下對(duì)數(shù)據(jù)模型進(jìn)行審核、測試,以及調(diào)優(yōu)。
審核分區(qū)和聚集鍵
在這個(gè)階段中,你需要將所有需要存儲(chǔ)的數(shù)據(jù)分配到一個(gè)或多個(gè)表中,并且這些表需要支持所需的訪問模式。下一步是檢查生成的數(shù)據(jù)模型是否有效地使用了Cassandra,如果沒有,則進(jìn)行調(diào)優(yōu)。在這個(gè)階段,需要檢查和調(diào)整的內(nèi)容包括:
分區(qū)鍵是否有足夠的基數(shù)?如果沒有,則可能需要將列從聚集鍵變?yōu)榉謪^(qū)鍵(例如,將主鍵(client_id,timestamp)更改為主鍵((client_id,timestamp)))或引入將多個(gè)聚集鍵分組為分區(qū)的新列(例如,將主鍵(client_id,timestamp)更改為主鍵((client_id,day),timestamp))。
分區(qū)鍵中的值是否會(huì)經(jīng)常更新?對(duì)主鍵的更新將導(dǎo)致記錄的刪除和重新插入。例如,在一個(gè)維護(hù)了所有客戶的狀態(tài)的表中,可能有主鍵(狀態(tài),客戶ID)。但是,這將導(dǎo)致每當(dāng)客戶狀態(tài)發(fā)生變化時(shí)都需要?jiǎng)h除并重新插入記錄。在這種情況下,最好選擇集合或列表數(shù)據(jù)類型,而不是將客戶ID作為聚集鍵。
每個(gè)分區(qū)中的記錄數(shù)是否有限制?特別大的分區(qū)和或者分布非常不均勻的分區(qū)可能會(huì)出現(xiàn)問題。例如,假設(shè)有一張client_updates表,其主鍵為(client_id,update_timestamp),則客戶記錄的更新次數(shù)可能并沒有限制,因?yàn)榭赡苡猩倭康目蛻粢呀?jīng)有10年未更新,而大多數(shù)客戶只有一兩天而已。
測試和調(diào)優(yōu)
最后一步,也可能是最重要的,即對(duì)數(shù)據(jù)模型進(jìn)行測試,并根據(jù)需要進(jìn)行調(diào)優(yōu)。請(qǐng)記住,像分區(qū)或記錄數(shù)增長過快的問題只有在實(shí)際負(fù)載下使用幾天(或更長時(shí)間)之后才能發(fā)現(xiàn)。因此,測試的時(shí)候需要盡可能地接近真實(shí)負(fù)載,并密切監(jiān)視各種警告信息(nodetool cfstats和cfhistograms命令對(duì)此非常有用)。
在這個(gè)階段,你也可以考慮調(diào)整一些影響數(shù)據(jù)物理存儲(chǔ)的設(shè)置。例如:
改變壓縮策略;
如果只使用TTL來刪除數(shù)據(jù)的話,則可以降低gc_grace_seconds,或者
設(shè)置緩存選項(xiàng)。
一個(gè)完整的例子
為了說明這一點(diǎn),下文將介紹一個(gè)示例,該示例構(gòu)建了一個(gè)數(shù)據(jù)庫,用于存儲(chǔ)和檢索來自多個(gè)服務(wù)器的日志消息。請(qǐng)注意,與大多數(shù)實(shí)際的案例相比,這個(gè)例子非常簡單。
步驟1:定義數(shù)據(jù)域
上面的ER圖描述了本示例的數(shù)據(jù)域,包括:
有很多(百萬數(shù)量級(jí))的日志消息,有時(shí)間戳和主體。盡管消息ID在ER圖中顯示為主鍵,但消息時(shí)間加消息類型是備用主鍵。
每個(gè)日志消息都有一個(gè)消息類型,多個(gè)類型被進(jìn)一步分組為一個(gè)消息類別(例如,消息類型可能是“內(nèi)存不足錯(cuò)誤”,類別可能是“錯(cuò)誤”)。有幾百個(gè)消息類型和大約20個(gè)類別。
每個(gè)日志消息來自一個(gè)消息源。消息源是生成消息的服務(wù)器。我們的系統(tǒng)中有1000臺(tái)服務(wù)器。每個(gè)消息源都有一個(gè)源類型對(duì)其進(jìn)行分類(如紅帽服務(wù)器、Ubuntu服務(wù)器、Windows服務(wù)器、路由器等)。有大約20個(gè)源類型。每個(gè)源每天有大約10000條消息。
消息體可以被解析并存儲(chǔ)為多個(gè)消息體(一般來說是鍵值對(duì))。每條消息通常不超過20個(gè)消息體。
步驟2:定義所需的訪問模式
我們需要能夠:
檢索給定源的最近10條消息的所有可用信息(并且能夠從中及時(shí)回溯)。
檢索給定源類型的最近10條消息的所有可用信息。
步驟3:確定主要訪問實(shí)體
這里有兩個(gè)主要訪問實(shí)體:源和源類型。源類型的基數(shù)(約為20)使其非常適合成為二級(jí)索引,所以我們將使用源作為主要訪問實(shí)體,并添加源類型為二級(jí)索引。
步驟4:分配次要實(shí)體
在這個(gè)例子中,這個(gè)步驟相對(duì)簡單,因?yàn)樗袛?shù)據(jù)都需要滾入到日志源主要訪問實(shí)體中。所以我們需要:
下推源類型名稱
下推消息類別和消息類型以記錄消息
上推日志消息,使其作為新實(shí)體的聚集鍵
作為map類型上推消息體。
最終這將是一個(gè)帶有源ID分區(qū)鍵和(消息時(shí)間,消息類型)聚集鍵的單個(gè)表。
步驟5:審核分區(qū)和聚集鍵
根據(jù)檢查清單檢查這些分區(qū)和聚集鍵:
分區(qū)鍵是否有足夠的基數(shù)?是的,有1000個(gè)源。
分區(qū)鍵中的值是否會(huì)經(jīng)常更新?不,所有的數(shù)據(jù)都是一次寫入的。
每個(gè)分區(qū)中的記錄數(shù)是否有限制?不,消息數(shù)可能會(huì)隨著時(shí)間的推移而無限地增長。所以,我們需要解決無限分區(qū)大小的問題。在時(shí)間序列數(shù)據(jù)中,解決這個(gè)問題的典型模式是將一組時(shí)間段引入到聚集鍵中。在這種情況下,每天10000條消息是一個(gè)比較合理的數(shù)字,可以包含在一個(gè)分區(qū)中,因此我們將使用“天”作為分區(qū)鍵的一部分。
最后,Cassandra結(jié)果表是這樣的:
CREATETABLEexample.log_messages ( message_id uuid, source_name text, source_type text, message_type text, message_urgencyint, message_category text, message_timetimestamp, message_time_day text, message_body text, message_parts map
?
評(píng)論
查看更多