拒絕列出分區
由於存取模式和資料建模,有時會有特定的分區「熱門」,並可能導致 Cassandra 群集不穩定。當資料模型在單一分區上包含許多更新或插入作業時,通常會發生這種情況,導致分區隨著時間推移而變得很龐大,進而使其讀取和維護成本很高。
Cassandra 支援「拒絕列出」這些有問題的分區,以便當客戶端發出點讀取(指定分區金鑰的 SELECT
陳述式)或範圍讀取(SELECT *
等,會提取資料範圍)與封鎖的分區金鑰相交時,查詢會立即以 InvalidQueryException
拒絕。
如何拒絕列出分區金鑰
system_distributed.denylisted_partitions
表格可用於拒絕列出分區。有幾種方式可以與這些資料互動並變更這些資料。首先:直接透過 CQL,透過插入具有下列詳細資料的記錄
-
Keyspace 名稱 (ks_name)
-
表格名稱 (table_name)
-
分區金鑰 (partition_key)
分區金鑰格式需要與 nodetool getendpoints
所需的格式相同。
以下是針對主鍵 Id
上不同資料類型,在 keyspace ks
和表格 table1
中取消拒絕列示分區金鑰的幾個範例
-
Id 是簡單類型 -
INSERT INTO system_distributed.denylisted_partitions (ks_name, table_name, partition_key) VALUES ('ks','table1','1');
-
Id 是 blob -
INSERT INTO system_distributed.denylisted_partitions (ks_name, table_name, partition_key) VALUES ('ks','table1','12345f');
-
Id 有冒號 -
INSERT INTO system_distributed.denylisted_partitions (ks_name, table_name, partition_key) VALUES ('ks','table1','1\:2');
在複合欄位分區金鑰 (Key1, Key2) 的情況下
-
INSERT INTO system_distributed.denylisted_partitions (ks_name, table_name, partition_key) VALUES ('ks', 'table1', 'k11:k21')
特殊考量
拒絕清單具有以下特性,您希望盡可能讓快取 (請參閱下方) 和 CQL 資料在複本組上保持接近,因此您不希望叢集中的不同節點拒絕或允許不同的金鑰。為了最佳達成此目標,拒絕清單變更 (新增或刪除) 的工作流程應始終如下
JMX 路徑 (建議用於單一變更)
-
使用想要的 key 呼叫
denylistKey()
的 JMX 勾子 -
使用
isKeyDenylisted()
再次檢查快取已重新載入 -
檢查有關無法辨識的 keyspace/table 組合、限制或一致性層級的警告。如果您收到有關節點已停用且未命中拒絕清單 CL 的訊息,請復原已停用的節點,然後使用
loadPartitionDenylist()
在每個節點上觸發快取重新載入
CQL 路徑 (建議用於大量變更)
-
透過 CQL 變更拒絕列示的分區清單
-
透過 JMX
loadPartitionDenylist()
在每個節點上觸發拒絕清單快取重新載入 (請參閱下方) -
檢查有關拒絕清單更新可用性不足的警告。如果節點已停用,請復原它們,然後前往 2。
由於已知無法使用的範圍切片在啟動時會導致警報風暴,因此除非拒絕清單快取可以在 cassandra.yaml
- denylist_consistency_level
中達成已設定的一致性層級,否則拒絕清單快取不會在節點啟動時載入。不過,無論可用節點數量為何,呼叫 loadPartitionDenylist
的 JMX 都會載入快取。這讓操作員可以控制在叢集狀態劣化期間是否拒絕列示。
已拒絕列示的分區快取
Cassandra 內部維護一個從 system_distributed.denylisted_partitions
載入的拒絕分區的堆內快取。資料表的值將會在 conf/cassandra.yaml
檔案中指定的 denylist_refresh
中自動重新填入,預設為 600s
,或 10 分鐘。無效的記錄(未知的鍵空間、資料表或金鑰)將會被忽略,且不會在載入時快取。
快取可以用以下方式重新整理
-
在 Cassandra 節點啟動期間
-
透過自動堆內快取重新整理機制。注意:這將會在查詢後非同步發生,在
denylist_refresh
時間命中之後。 -
透過 JMX 指令:
loadPartitionDenylist
在the org.apache.cassandra.service. StorageProxyMBean
呼叫點。
快取大小受以下兩個設定屬性限制
-
denylist_max_keys_per_table
-
denylist_max_keys_total
在快取載入時,如果資料表超過 denylist_max_keys_per_table
中允許的值(預設為 1000),將會在記錄中印出警告,且其餘的金鑰將不會快取。類似地,如果超過允許的總大小,後續的 ks_name + table_name 組合(以分群/字順排序)也會被略過,且會在伺服器記錄中記錄警告。
考量到 1) 變更、2) 重新載入快取的必要工作流程,自動重新載入屬性似乎是多餘的。它的存在是為了確保,如果操作員錯誤地拒絕或取消拒絕金鑰,但忘記重新載入快取,該意圖將會在下次快取重新載入時擷取。 |
JMX 介面
指令 | 效果 |
---|---|
loadPartitionDenylist() |
從 CQL 資料表重新載入快取的拒絕清單 |
getPartitionDenylistLoadAttempts() |
取得快取重新載入嘗試次數 |
getPartitionDenylistLoadSuccesses() |
取得快取重新載入成功的次數 |
setEnablePartitionDenylist(boolean enabled) |
啟用或停用分區拒絕清單功能 |
setEnableDenylistWrites(boolean enabled) |
啟用或停用寫入拒絕清單功能 |
setEnableDenylistReads(boolean enabled) |
啟用或停用讀取拒絕清單功能 |
setEnableDenylistRangeReads(boolean enabled) |
啟用或停用範圍讀取拒絕清單功能 |
denylistKey(String keyspace, String table, String partitionKeyAsString) |
將特定的鍵空間、表格和分區金鑰組合新增至拒絕清單 |
removeDenylistKey(String keyspace, String cf, String partitionKeyAsString) |
從拒絕清單中移除特定的鍵空間、表格和分區金鑰組合 |
setDenylistMaxKeysPerTable(int value) |
限制拒絕清單中每個表格允許的金鑰數量 |
setDenylistMaxKeysTotal(int value) |
限制系統中允許拒絕清單金鑰的總數量 |
isKeyDenylisted(String keyspace, String table, String partitionKeyAsString) |
指出 keyspace.table 是否拒絕輸入的分區金鑰 |