2015-12-24 48 views
1

我第一次和Cassandra一起玩,我覺得我理解了基本知識和限制。作爲示例,我正在使用以下模型來存儲通過hashtag收集的推文。在Cassandra中定義分區鍵

create table posts 
(
    id text, 
    status text, 
    service text, 
    hashtag text, 
    username text, 
    caption text, 
    image text, 
    link text, 
    repost boolean, 
    created timestamp, 
    primary key (hashtag, created) 
); 

這非常適用於查詢的類型,我需要:

select * from posts where hashtag = 'demo' order by created desc; 

但是,如果我理解正確的事情,有一個上限,我可以存儲使用奇異的職位數'demo'分區鍵,更重要的是,與「演示」分區鍵匹配的整個帖子集必須與每個副本一起存儲。如果我理解正確,我應該使用更隨機或可變的分區鍵(可能是文章的id),但我不知道如何使用這些鍵不會改變查詢的要求。

如果我使用id作爲分區鍵(如PRIMARY KEY (id, created))和#標籤欄添加輔助指標,我收到以下錯誤,當我運行我的查詢:

ORDER BY with 2ndary indexes is not supported. 

我得到使用ORDER BY,分區鍵必須在where子句中顯示,因此我最初的想法是使用hashtag。

我在推翻事物還是有更好的候選分區鍵?

回答

2

你走的方向取決於你期望的寫入量和你的羣集有多大。

如果您有一個小型用戶社區和一個小型羣集,那麼您可能會過度揣測事物。理論上分區可以容納20億行。這是一個很大的數字,並且任何人都希望查看超過幾千個最新的推文標籤?所以你可能會有一些清理機制,比如在一段時間後使用TTL刪除推文,這將釋放分區中的空間,使你遠低於20億行的限制。

如果你不想清理舊鳴叫,但希望保留他們很多年,那麼你可能想使用這樣的複合分區鍵:

primary key ((hashtag, year), created) 

這將分區鳴叫按標籤和年份計算,因此每年每個標籤最多可存儲20億條推文。

通過hashtag進行分區的好處在於,Cassandra可以保留按照創建時間戳排序的標籤的推文,使您可以輕鬆地使用單個查詢檢索最近的推文。

但是,如果你的用戶社區很大,那麼更大的問題是避免熱點問題。如果您只使用哈希標籤和像年份這樣的時間段作爲分區鍵,則所有讀取和寫入操作都將針對該哈希標籤的少量副本。如果哈希標籤在某一天非常活躍,那麼根據您使用的複製因素,您的所有讀取和寫入都只會變爲一個或兩個節點。

如果要分散讀寫負載,則需要增加hashtag的基數,使其映射到多個節點。使用id作爲分區鍵可以實現這一目標,但是這樣做會過於頻繁,因爲每條推文都會位於一個單獨的分區中,您將無法通過排序或簡單的方式檢索最新的推文標籤。

所以,更好的方法是創建單獨的箱或桶,這樣的:

primary key ((hashtag, bin), created) 

創建箱的數量取決於你的寫入負載。假設您決定10個節點可以處理熱標籤的寫入負載,那麼bin的值將爲0到9.

有許多方法可以設置bin編號。你可以用10進行一個模的id,或者從0到9之間選擇一個隨機數,或者從一些字段組合中產生一個散列值,並取模10的結果。無論您選擇哪種方法,都要確保0到9之間的數字具有相同的可能性,以便您的數據在整個分區中均勻分佈。

對於多個箱,檢索hashtag的x個最近鳴叫並不容易,因爲您需要查詢所有箱併合並結果。您可以並行地爲並行的hashtag的每個bin發出查詢,然後在客戶端合併結果。或者你也可以使用IN子句這樣做的一個查詢:

select * from posts where hashtag = 'demo' and bin IN (0,1,2,3,4,5,6,7,8,9) AND created > ... 

但卡桑德拉不會對單個查詢的結果進行排序,所以你必須做一個排序在客戶端,這是比合並單獨的有序查詢要慢。

現在很多情況下會有音量標籤很少的標籤,因此您可能不想打擾使用十個垃圾箱,除非它們變熱。如果是這樣,您可以在應用程序中使其變爲動態的,通常只使用bin 0,但隨後在發現標記受歡迎時增加bin的數量。您可以使用bin 0中的靜態列來跟蹤hashtag的活動bin的數量。

您應該避免使用二級索引。他們在卡桑德拉效率很低。

+0

嗨。爲了讓你的答案更加有用,你可以添加一個示例或鏈接到描述如何最有效地執行客戶端「合併_separate ordered queries_」的資源(例如在Java中)嗎?謝謝。 – user909481