2015-05-19 15 views
3

我有一個三個Cassandra節點的集羣,具有或多或少的默認配置。最重要的是,我有一個由兩個節點組成的web層負載均衡,這兩個web節點都一直在查詢Cassandra。一段時間後,隨着Cassandra中存儲的數據變得不平凡,一個且僅有的一個Web節點開始在特定查詢中獲得ReadTimeoutException。網絡節點在各個方面都是相同的。奇怪的Cassadra ReadTimeoutExceptions,取決於哪個客戶端正在查詢

的查詢非常簡單(?是日期佔位符,當前時刻之前,通常在幾分鐘):

SELECT * FROM table WHERE time > ? LIMIT 1 ALLOW FILTERING; 

表與此查詢創建:

CREATE TABLE table (
    user_id varchar, 
    article_id varchar, 
    time timestamp, 
    PRIMARY KEY (user_id, time)); 
CREATE INDEX articles_idx ON table(article_id); 

當超時,客戶端會等待10秒以上,這並不奇怪,對於大多數連接和讀取,在cassandra.yaml中配置了超時。

有一對夫婦的事情,是我莫名其妙:

  • 查詢只有當網絡節點中的一個執行它超時 - 節點中的一個總是失敗,其中一個節點總是成功。
  • 查詢將返回瞬間,當我從cqlsh運行(儘管它似乎只命中,當我從那裏運行它的一個節點)
  • 有發出其他查詢這需要2-3分鐘(有很多比10秒長超時)根本沒有超時

我無法在Java中跟蹤查詢,因爲它超時。追蹤cqlsh中的查詢並沒有提供太多的見解。我寧願不更改Cassandra超時,因爲這是生產系統,我想先耗盡非侵入性選項。 Cassandra節點都有很多堆,堆很遠,GC時間看起來很正常。

任何想法/方向將不勝感激,我完全沒有想法。 Cassandra版本是2.0.2,使用com.datastax.cassandra:cassandra-driver-core:2.0.2 Java客戶端。

+0

此表中有多少行? – Aaron

+0

在cqlsh中設置不同的一致性級別,然後再試一次 –

+0

@ BryceAtNetwork23:<100 million – sbk

回答

3

有幾件事情,我注意到:

  1. 當您使用time作爲聚集鍵,它並沒有真正幫助你,因爲你的查詢不被你的分區鍵(user_id)限制。 Cassandra僅通過在分區內對密鑰進行分組來命令。所以,現在您的查詢將回退滿足您的WHERE子句的第一行,按散列標記值user_id排序。如果你真的有數千萬行,那麼我希望這個查詢每次都從相同的user_id(或相同的幾個選擇)中撤回數據。

  2. 「但現在看來,這只是擊中時,我從那裏運行一個節點」其實,你的查詢應該只有當你運行它們打一個節點。將網絡流量引入查詢使其非常慢。我認爲cqlsh的默認一致性是ONE。這就是卡羅的想法開始發揮作用。

  3. article_id的基數是多少?請記住,二級指標在「中間道路」基數方面效果最好。高(唯一)和低(布爾)都不好。

  4. ALLOW FILTERING子句不應用於(生產)應用程序端代碼。像以往一樣。如果你在這個表中有5000萬行,那麼ALLOW FILTERING首先把它們全部拉回來,然後根據你的WHERE子句修剪結果集。

建議:

  1. 卡羅可能將要發生什麼用的嘗試不同(更低)的一致性水平的建議。嘗試在應用程序中設置一致性級別ONE,看看是否有幫助。

  2. 要麼執行ALLOW FILTERING查詢,要麼執行輔助索引查詢。他們都吮吸,但絕對不會一起做。我也不會使用。但是,如果我不得不選擇,我會期望一個輔助索引查詢吸入少於ALLOW FILTERING查詢。

  3. 爲了在您所描述的規模下充分解決這個問題,我會將數據複製到查詢表中。因爲您看起來像關心組織對時間敏感的數據以及獲取最新數據。像這樣的查詢表應該這樣做:

    CREATE TABLE tablebydaybucket ( user_id varchar, article_id varchar, time timestamp, day_bucket varchar, PRIMARY KEY (day_bucket , time)) WITH CLUSTERING ORDER BY (time DESC);

填充此表與您的數據,然後該查詢將工作:

SELECT * FROM tablebydaybucket 
WHERE day_bucket='20150519' AND time > '2015-05-19 15:38:49-0500' LIMIT 1; 

這將day_bucket分區數據,並通過time將您的數據集羣。這樣,你將不需要ALLOW FILTERING或二級索引。此外,您的查詢將保證只能訪問一個節點,並且Cassandra不必將所有行取回並在事後應用WHERE子句。並且按照DESCending順序在time上聚類,可幫助您最近的行更快地恢復。

+0

這非常有見地,謝謝!查詢來自應用程序運行狀況檢查 - 我們期望連續的數據流,並且如果沒有新行,則會出現問題(因此,只接收一個user_id的記錄不是問題)。實際的應用程序代碼僅通過used_id進行選擇。 在任何情況下,似乎都沒有解釋爲什麼查詢在從一個框中執行時會持續失敗,並且從另一個框持續成功。 – sbk

相關問題