常見問題
為何我無法將 listen_address
設定為監聽 0.0.0.0(我所有的位址)?
Cassandra 是基於八卦的分布式系統,而 listen_address
是節點告知其他節點用來連線的位址。告知其他節點「透過我的任何位址與我連線」並非好主意;如果叢集中的不同節點為您選擇不同的位址,就會發生不好的事情。
如果您不想手動為叢集中每個節點的 listen_address
指定 IP(可以理解!),請將其留空,Cassandra 會使用 InetAddress.getLocalHost()
選擇位址。然後,您或您的運作團隊必須讓事情正確解析(/etc/hosts/
、dns 等)。
這個程序的一個例外是 JMX,它預設會繫結至 0.0.0.0(Java 錯誤 6425769)。
請參閱 256
和 43
以取得更詳細的資訊。
Cassandra 使用哪些埠?
預設情況下,Cassandra 使用 7000 進行叢集通訊(如果啟用 SSL,則為 7001),使用 9042 進行原生通訊協定用戶端,以及使用 7199 進行 JMX。節點間通訊和原生通訊協定埠可以在 cassandra-yaml
中設定。JMX 埠可以在 cassandra-env.sh
(透過 JVM 選項)中設定。所有埠都是 TCP。
我從 Cassandra 刪除資料,但磁碟使用量保持不變。這是怎麼回事?
您寫入 Cassandra 的資料會持續到 SSTable。由於 SSTable 是不可變的,因此當您執行刪除時,資料實際上無法移除,而是會寫入一個標記(也稱為「墓碑」)來表示該值的最新狀態。不過不用擔心,在資料和墓碑之間發生的第一次壓縮中,資料將會被完全清除,並回收對應的磁碟空間。請參閱 compaction
以取得更多詳細資訊。
即使我的節點已記錄到它們看到彼此加入環,為什麼 nodetool ring 只顯示一個條目?
當您將相同的代幣分配給每個節點時,就會發生這種情況。不要這樣做。
最常發生這種情況的人是透過在 VM 上安裝 Cassandra 來部署的人(特別是在使用 Debian 套件時,該套件會在安裝後自動啟動 Cassandra,從而產生並儲存代幣),然後將該 VM 克隆到其他節點。
最簡單的修復方法是清除資料和提交日誌目錄,從而確保每個節點在下一次重新啟動時產生隨機代幣。
我可以在執行中的叢集上變更複製因子(a a 鍵空間)嗎?
可以,但需要執行完整修復(或清除)才能變更現有資料的複製品數量
-
Alter <alter-keyspace-statement>
複製因子以取得所需的鍵空間(例如使用 cqlsh)。 -
如果您要減少複製因子,請在叢集上執行
nodetool cleanup
以移除多餘的複製品資料。清除會逐節點執行。 -
如果您要增加複製因子,請執行
nodetool repair -full
以確保資料根據新設定進行複制。修復會逐複製品組執行。這是一個密集的程序,可能會導致叢集效能不佳。強烈建議進行滾動修復,因為嘗試一次修復整個叢集很可能會淹沒它。請注意,您需要執行完整修復(-full
)以確保不會跳過已修復的 SSTable。您應使用ConsistencyLevel.QUORUM
或ALL
(取決於您現有的複製因子)以確保會諮詢實際擁有資料的複製品。否則,一些客戶端可能會被告知在修復完成之前沒有資料。
我可以在 Cassandra 中儲存(大型)BLOB 嗎?
Cassandra 沒有針對大型檔案或 BLOB 儲存進行最佳化,而且單一 blob
值總是會讀取並完整傳送給客戶端。因此,儲存小型 BLOB(小於個位數 MB)不應構成問題,但建議手動將大型 BLOB 分割成較小的區塊。
請特別注意,預設情況下,任何大於 16MiB 的值都會被 Cassandra 拒絕,因為 cassandra-yaml
檔案的 max_mutation_size
組態(預設為 commitlog_segment_size
的一半,而 commitlog_segment_size
本身預設為 32MiB)。
Nodetool 對任何遠端主機都顯示「Connection refused to host: 127.0.1.1」。這是怎麼回事?
Nodetool 依賴於 JMX,而 JMX 又依賴於 RMI,而 RMI 又會在交換的每一端根據需要設定自己的監聽器和連接器。通常,所有這些都會在幕後透明地發生,但是連接主機或被連接主機的名稱解析不正確,可能會導致連線錯誤和令人困惑的例外狀況。
如果您沒有使用 DNS,請確保兩端的 /etc/hosts
檔案都正確無誤。如果這樣做失敗,請嘗試在 cassandra-env.sh
的底部附近設定 -Djava.rmi.server.hostname=<public name>
JVM 選項,以設定一個可以從遠端機器存取的介面。
批次處理我的作業會加速我的大量載入嗎?
不會。使用批次處理載入資料通常只會增加延遲的「尖峰」。請改用非同步 INSERT,或使用真正的 bulk-loading
。
例外情況是批次處理對單一分區的更新,這可能是件好事(只要單一批次的大小保持合理)。但千萬不要盲目地批次處理所有內容!
在 RHEL 節點上無法加入環狀網路
檢查 SELinux 是否已開啟;如果已開啟,請關閉它。
為什麼 top 報告 Cassandra 使用的記憶體遠多於 Java 堆積最大值?
Cassandra 在內部使用 記憶體對應檔案 (mmap)。也就是說,我們使用作業系統的虛擬記憶體系統將許多磁碟檔案對應到 Cassandra 程序的位址空間。這將「使用」虛擬記憶體;換句話說,位址空間,並且會由 top 等工具相應地報告,但在 64 位元系統上,虛擬位址空間實際上是無限的,所以您不必擔心這一點。
從「記憶體使用」的角度來看,重要的是在 brk() 或 mmap’d /dev/zero 上配置的資料量,它們代表實際使用的記憶體。關鍵問題是,對於 mmap’d 檔案,從不需要將資料保留在實體記憶體中。因此,無論您將什麼資料保留在實體記憶體中,基本上都只是作為快取存在,就像正常的 I/O 會導致核心頁面快取保留您讀取/寫入的資料一樣。
mmap() 與一般 I/O 的差異在於,mmap() 的情況下,記憶體實際上會對應到程序,因此會影響 top 所回報的虛擬大小。使用 mmap() 而非標準 I/O 的主要論點在於,讀取僅需觸及記憶體,如果記憶體為駐留狀態,您只需讀取它,甚至不會發生分頁錯誤(因此不會有進入核心和執行半上下文切換的負擔)。此處有更詳細的說明。
種子是什麼?
種子用於啟動期間發現叢集。
如果您將節點設定為將某個節點視為種子,則環中的節點會比非種子更常將 Gossip 訊息傳送給種子(另請參閱有關八卦 <gossip>
的章節)。換句話說,種子用作 Gossip 網路的樞紐。有了種子,每個節點都可以快速偵測其他節點的狀態變更。
新節點在開機時也會參考種子以了解環中的其他節點。當您將新節點加入環時,您需要指定至少一個要連繫的有效種子。一旦節點加入環,它就會了解其他節點,因此在後續開機時不需要種子。
您可以在任何時候將節點設為種子。種子節點沒有什麼特別之處。如果您在種子清單中列出節點,它就是種子
種子不會自動開機(也就是說,如果節點在自己的種子清單中,它不會自動將資料傳輸給自己)如果您希望節點執行此動作,請先開機,然後再將它加入種子。如果您沒有資料(新安裝),您完全不必擔心開機。
種子的建議用法
-
每個資料中心選取兩個(或更多)節點作為種子節點。
-
將種子清單同步到您所有的節點
為什麼我無法在 jconsole 上呼叫 jmx 方法 X?
某些 JMX 作業使用陣列引數,而 jconsole 不支援陣列引數,因此這些作業無法使用 jconsole 呼叫(按鈕對它們而言是處於非活性狀態)。您需要撰寫一個 JMX 程式來呼叫此類作業,或需要支援陣列的 JMX 監控工具。
為什麼我在記錄中看到「… 已捨棄訊息 …」?
這是負載捨棄的症狀,Cassandra 會自我防禦超過其所能處理的請求。
節點接收到的節點間訊息,但在適當的逾時時間內未得到處理(請參閱 cassandra-yaml 中的 read_request_timeout、write_request_timeout、…),會被捨棄而不是處理(因為協調節點將不再等待回應)。
對於寫入,這表示變更並未套用至傳送給它的所有複本。不一致性將透過讀取修復、提示或手動修復來修復。寫入作業也可能因此逾時。
對於讀取,這表示讀取請求可能尚未完成。
負載捨棄是 Cassandra 架構的一部分,如果這是一個持續性的問題,通常表示節點或叢集過載。
Cassandra 會因「java.lang.OutOfMemoryError: Map failed」而死掉
如果 Cassandra 特別是因為「Map failed」訊息而死掉,表示作業系統拒絕 java 鎖定更多記憶體。在 linux 中,這通常表示 memlock 受到限制。檢查 /proc/<pid of cassandra>/limits 以驗證這一點並提高它(例如,透過 bash 中的 ulimit)。您可能還需要增加 vm.max_map_count。請注意,debian 套件會自動為您處理這件事。
如果使用相同時間戳記進行兩次更新,會發生什麼事?
更新必須是可交換的,因為它們可能以不同的順序到達不同的複本。只要 Cassandra 有確定性的方式來選擇獲勝者(在時間戳記平手時),所選的獲勝者與任何其他獲勝者一樣有效,而具體細節應視為實作細節。話雖如此,在時間戳記平手的情況下,Cassandra 會遵循兩個規則:首先,刪除優先於插入/更新。其次,如果有兩個更新,則會選取字元較大的更新。
為什麼以「串流失敗」錯誤啟動新節點會失敗?
兩個主要可能性
-
GC 可能會造成長時間暫停,中斷串流處理
-
背景中發生的壓縮會讓串流保持足夠長的時間,導致 TCP 連線失敗
在第一種情況下,套用一般 GC 調整建議。在第二種情況下,您需要將 TCP 保持連線設定為較低的值(Linux 上的預設值很高)。請嘗試執行以下操作
$ sudo /sbin/sysctl -w net.ipv4.tcp_keepalive_time=60 net.ipv4.tcp_keepalive_intvl=60 net.ipv4.tcp_keepalive_probes=5
若要讓這些設定永久生效,請將它們新增到您的 /etc/sysctl.conf
檔案。
注意:GCE 的防火牆會在 TCP 連線閒置超過 10 分鐘時中斷連線。強烈建議在該環境中執行上述指令。