完整查詢記錄
Apache Cassandra 4.0 新增一項新的高性能功能,支援即時查詢記錄 (CASSANDRA-13983)。FQL 安全可用於生產環境,並可設定堆積記憶體和磁碟空間的限制,以防止記憶體不足錯誤。此功能對即時流量擷取和流量重播很有用。所提供的工具可用於偵錯查詢流量和移轉。也新增了新的 nodetool
選項,以啟用、停用或重設 FQL,以及一個新的工具來讀取和重播二進位記錄。完整查詢記錄 (FQL) 功能使用 Chronicle-Queue 來輪替查詢記錄。完整查詢記錄在剩餘頁面中將稱為記錄。
FQL 的一些功能包括
-
非同步單一執行緒記錄項目寫入磁碟,可降低對查詢延遲的影響。
-
堆積記憶體使用量受到加權佇列限制,可設定最大加權值,並置於記錄執行緒之前。
-
如果加權佇列已滿,則生產者可能會被封鎖,或範例可能會被捨棄。
-
磁碟使用量受到可設定大小的限制,一旦達到限制,就會刪除舊的記錄區段。
-
一個彈性的架構二進位格式 Chronicle-Wire,用於磁碟上序列化,可以略過未辨識的欄位,新增新的欄位,並省略舊的欄位。
-
可以使用 JMX 工具、
nodetool
來啟用、停用或重設(刪除磁碟資料)。 -
可以在
cassandra.yaml
檔案中設定設定,或使用nodetool
設定。 -
推出新的
fqltool
,目前可以將二進位記錄檔轉儲為可讀格式。其他選項包括Replay
和Compare
。
FQL 會記錄所有成功的 Cassandra 查詢語言 (CQL) 要求,包括修改資料和查詢的事件。雖然稽核記錄也會包含 CQL 要求,但 FQL 只會記錄 CQL 要求。這個差異表示 FQL 可用於重播或比較記錄檔,而稽核記錄無法做到。FQL 對於除錯、效能基準測試、測試和稽核 CQL 查詢很有用,而稽核記錄則對於合規很有用。
在效能測試中,FQL 在只有 WRITE
的工作負載中似乎沒有或幾乎沒有負擔,而在 MIXED
工作負載中則有輕微的負擔。
記錄的查詢資訊
查詢記錄檔包含
-
呼叫的所有查詢
-
呼叫它們的近似時間
-
繫結萬用字元值所需的任何參數
-
所有查詢選項
記錄器會在 CQL 查詢完成後寫入單一或批次 CQL 查詢,因此只會記錄成功完成的查詢。失敗或逾時的查詢不會記錄。記錄的資料會根據查詢類型而有所不同。
單一 CQL 查詢記錄項目包含
-
query - CQL 查詢文字
-
queryOptions - 與查詢呼叫相關聯的選項
-
queryState - 與查詢呼叫相關聯的時間戳記狀態
-
queryTimeMillis - 自查詢呼叫以來,自紀元以來的近似時間(毫秒)
批次 CQL 查詢記錄項目包含
-
queries - 查詢的 CQL 文字
-
queryOptions - 與查詢呼叫相關聯的選項
-
queryState - 與查詢呼叫相關聯的時間戳記狀態
-
batchTimeMillis - 自批次呼叫以來,自紀元以來的近似時間(毫秒)
-
type - 批次的類型
-
values - 要繫結為查詢參數的值
由於 FQL 由 Binlog
支援,因此效能和佔用空間是可預測的,對記錄記錄產生器的影響很小。效能安全可防止產生器過載記錄,使用加權佇列在記錄落後時捨棄記錄。單執行緒非同步寫入會產生記錄檔。Chronicle-Queue 提供了一種輕鬆的方法來滾動記錄檔。
記錄順序
記錄器會遵循一連串定義良好的事件
-
撰寫記錄記錄的消費者執行緒已啟動。此動作只能執行一次。
-
消費者執行緒會提供記錄給記錄檔。如果記憶體內佇列已滿,記錄將會被捨棄,而提供會傳回
false
值。 -
如果已接受,記錄會輸入記錄檔。如果記憶體內佇列已滿,放置執行緒會被封鎖,直到有空間或中斷為止。
-
執行緒結束時會清除緩衝區。完成處理會再次檢查,以確保佇列中沒有落後者。
-
消費者執行緒已停止。可以呼叫多次。
使用 FQL
若要使用 FQL,必須完成兩個動作。必須使用 cassandra.yaml
檔案或 nodetool
設定 FQL,並使用 nodetool enablefullquerylog
啟用記錄。使用任一種方法,至少必須指定記錄目錄的路徑。兩個動作都是以每個節點為基礎完成。每個已啟用的節點都會產生完整的查詢記錄,因此每個節點上的記錄都會有該節點的查詢。
在 cassandra.yaml 中設定 FQL
cassandra.yaml
檔案可用於在使用 nodetool
啟用功能之前設定 FQL。
檔案包含下列可用於取消註解以供使用的選項
# default options for full query logging - these can be overridden from command line
# when executing nodetool enablefullquerylog
#full_query_logging_options:
# log_dir:
# roll_cycle: HOURLY
# block: true
# max_queue_weight: 268435456 # 256 MiB
# max_log_size: 17179869184 # 16 GiB
# archive command is "/path/to/script.sh %path" where %path is replaced with the file being rolled:
# archive_command:
# max_archive_retries: 10
log_dir
若要撰寫記錄,必須在 log_dir
中設定現有目錄。
目錄必須設定適當的權限,以允許讀取、寫入和執行。記錄會根據需要遞迴刪除目錄內容。請勿將連結放置在此目錄中以連結到檔案系統的其他區段。例如,log_dir: /tmp/cassandrafullquerylog
。
max_queue_weight
max_queue_weight
選項設定等待寫入檔案的記錄在記憶體內佇列中的最大權重,然後封鎖或捨棄。選項必須設定為正值。預設值為 268435456,或 256 MiB。例如,若要變更預設值:max_queue_weight: 134217728 # 128 MiB
max_log_size
max_log_size
選項設定滾動檔案保留在磁碟上並刪除最舊檔案前的最大大小。此選項必須設定為正值。預設值為 17179869184,或 16 GiB。例如,若要變更預設值:max_log_size: 34359738368 # 32 GiB
啟用 FQL
使用 nodetool enablefullquerylog
指令在每個節點上啟用 FQL。至少必須定義記錄目錄的路徑,如果 log_dir
未設定在 cassandra.yaml
檔案中。
nodetool enablefullquerylog
指令的語法具有所有可以在 cassandra.yaml
檔案中設定的選項。此外,nodetool
有選項設定要執行指令的主機和埠,以及指令需要驗證時的使用者名稱和密碼。
nodetool [(-h <host> | --host <host>)] [(-p <port> | --port <port>)]
[(-pp | --print-port)] [(-pw <password> | --password <password>)]
[(-pwf <passwordFilePath> | --password-file <passwordFilePath>)]
[(-u <username> | --username <username>)] enablefullquerylog
[--archive-command <archive_command>] [--blocking]
[--max-archive-retries <archive_retries>]
[--max-log-size <max_log_size>] [--max-queue-weight <max_queue_weight>]
[--path <path>] [--roll-cycle <roll_cycle>]
OPTIONS
--archive-command <archive_command>
Command that will handle archiving rolled full query log files.
Format is "/path/to/script.sh %path" where %path will be replaced
with the file to archive
--blocking
If the queue is full whether to block producers or drop samples.
-h <host>, --host <host>
Node hostname or ip address
--max-archive-retries <archive_retries>
Max number of archive retries.
--max-log-size <max_log_size>
How many bytes of log data to store before dropping segments. Might
not be respected if a log file hasn't rolled so it can be deleted.
--max-queue-weight <max_queue_weight>
Maximum number of bytes of query data to queue to disk before
blocking or dropping samples.
-p <port>, --port <port>
Remote jmx agent port number
--path <path>
Path to store the full query log at. Will have it's contents
recursively deleted.
-pp, --print-port
Operate in 4.0 mode with hosts disambiguated by port number
-pw <password>, --password <password>
Remote jmx agent password
-pwf <passwordFilePath>, --password-file <passwordFilePath>
Path to the JMX password file
--roll-cycle <roll_cycle>
How often to roll the log file (MINUTELY, HOURLY, DAILY).
-u <username>, --username <username>
Remote jmx agent username
若要啟用 FQL,請在叢集中您要啟用記錄的每個節點上執行下列指令
$ nodetool enablefullquerylog --path /tmp/cassandrafullquerylog
停用或重設 FQL
使用 nodetool disablefullquerylog
停用記錄。使用 nodetool resetfullquerylog
停止 FQL 並清除已設定目錄中的日誌檔案。重要:使用 nodetool resetfullquerylog
會刪除日誌檔案!除非您需要刪除所有日誌檔案,否則請勿使用此指令。
fqltool
fqltool
指令用於檢視 (傾印)、重播或比較日誌。fqltool dump
會將二進位日誌檔案轉換成人類可讀的格式;只有日誌目錄必須提供為指令列選項。
fqltool replay
(CASSANDRA-14618) 啟用日誌重播。此指令可從不同的機器或叢集執行,以進行測試、偵錯或效能基準測試。此指令也可拿來重新建立已刪除的資料庫物件。使用 fqltool replay
記錄並比較不同版本的 Cassandra 或不同叢集的生產流量。另一種用途是從多部機器收集日誌,並按記錄的時間戳順序「依序」重播。
fqltool replay
的語法為
fqltool replay [--keyspace <keyspace>] [--results <results>]
[--store-queries <store_queries>] --target <target>... [--] <path1>
[<path2>...<pathN>]
OPTIONS
--keyspace <keyspace>
Only replay queries against this keyspace and queries without
keyspace set.
--results <results>
Where to store the results of the queries, this should be a
directory. Leave this option out to avoid storing results.
--store-queries <store_queries>
Path to store the queries executed. Stores queries in the same order
as the result sets are in the result files. Requires --results
--target <target>
Hosts to replay the logs to, can be repeated to replay to more
hosts.
--
This option can be used to separate command-line options from the
list of argument, (useful when arguments might be mistaken for
command-line options
<path1> [<path2>...<pathN>]
Paths containing the FQ logs to replay.
fqltool compare
(CASSANDRA-14619) 比較 fqltool replay
所產生的結果檔案。此指令使用 fqltool replay
記錄的執行結果,並比較日誌,輸出任何差異(可能是所有查詢)。它也會將每列儲存為一個獨立的編年文件,以避免在比較時從記憶體中讀取整個結果。
fqltool compare
的語法為
fqltool compare --queries <queries> [--] <path1> [<path2>...<pathN>]
OPTIONS
--queries <queries>
Directory to read the queries from. It is produced by the fqltool
replay --store-queries option.
--
This option can be used to separate command-line options from the
list of argument, (useful when arguments might be mistaken for
command-line options
<path1> [<path2>...<pathN>]
Directories containing result files to compare.
比較會設定下列標記
-
標記查詢集的開頭
version: int16
type: column_definitions
column_count: int32;
column_definition: text, text
column_definition: text, text
....
-
標記失敗的查詢集
version: int16
type: query_failed
message: text
-
標記列集
version: int16
type: row
row_column_count: int32
column: bytes
-
標記結果集的結尾
version: int16
type: end_resultset
範例
-
要示範 FQL,請先在叢集中的節點上設定並啟用 FQL
$ nodetool enablefullquerylog --path /tmp/cassandrafullquerylog
-
現在使用
cqlsh
建立一個示範鍵空間和表格,並插入一些資料
cqlsh> CREATE KEYSPACE querylogkeyspace
... WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1};
cqlsh> USE querylogkeyspace;
cqlsh:querylogkeyspace> CREATE TABLE t (
...id int,
...k int,
...v text,
...PRIMARY KEY (id)
... );
cqlsh:querylogkeyspace> INSERT INTO t (id, k, v) VALUES (0, 0, 'val0');
cqlsh:querylogkeyspace> INSERT INTO t (id, k, v) VALUES (0, 1, 'val1');
-
然後檢查資料是否已插入
cqlsh:querylogkeyspace> SELECT * FROM t;
id | k | v
----+---+------
0 | 1 | val1
(1 rows)
-
使用
fqltool dump
指令檢視日誌。
$ fqltool dump /tmp/cassandrafullquerylog
此指令會傳回日誌的可讀版本。以下是此示範中指令的日誌部分範例
WARN [main] 2019-08-02 03:07:53,635 Slf4jExceptionHandler.java:42 - Using Pauser.sleepy() as not enough processors, have 2, needs 8+
Type: single-query
Query start time: 1564708322030
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:1564708322
Query: SELECT * FROM system.peers
Values:
Type: single-query
Query start time: 1564708322054
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:1564708322
Query: SELECT * FROM system.local WHERE key='local'
Values:
Type: single-query
Query start time: 1564708322109
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:1564708322
Query: SELECT * FROM system_schema.keyspaces
Values:
Type: single-query
Query start time: 1564708322116
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:1564708322
Query: SELECT * FROM system_schema.tables
Values:
Type: single-query
Query start time: 1564708322139
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:1564708322
Query: SELECT * FROM system_schema.columns
Values:
Type: single-query
Query start time: 1564708322142
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:1564708322
Query: SELECT * FROM system_schema.functions
Values:
Type: single-query
Query start time: 1564708322141
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:1564708322
Query: SELECT * FROM system_schema.aggregates
Values:
Type: single-query
Query start time: 1564708322143
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:1564708322
Query: SELECT * FROM system_schema.types
Values:
Type: single-query
Query start time: 1564708322144
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:1564708322
Query: SELECT * FROM system_schema.indexes
Values:
Type: single-query
Query start time: 1564708322145
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:1564708322
Query: SELECT * FROM system_schema.views
Values:
Type: single-query
Query start time: 1564708345408
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:-2147483648
Query: CREATE KEYSPACE querylogkeyspace
WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1};
Values:
Type: single-query
Query start time: 1564708360873
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:-2147483648
Query: USE querylogkeyspace;
Values:
Type: single-query
Query start time: 1564708360874
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:-2147483648
Query: USE "querylogkeyspace"
Values:
Type: single-query
Query start time: 1564708378837
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:-2147483648
Query: CREATE TABLE t (
id int,
k int,
v text,
PRIMARY KEY (id)
);
Values:
Type: single-query
Query start time: 1564708379247
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:1564708379
Query: SELECT * FROM system_schema.tables WHERE keyspace_name = 'querylogkeyspace' AND table_name = 't'
Values:
Type: single-query
Query start time: 1564708397144
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:1564708397
Query: INSERT INTO t (id, k, v) VALUES (0, 0, 'val0');
Values:
Type: single-query
Query start time: 1564708434782
Protocol version: 4
Generated timestamp:-9223372036854775808
Generated nowInSeconds:1564708434
Query: SELECT * FROM t;
Values:
-
要示範
fqltool replay
,請先刪除鍵空間。
cqlsh:querylogkeyspace> DROP KEYSPACE querylogkeyspace;
-
現在執行
fqltool replay
,並分別在--results
和--store-queries
中指定要儲存查詢結果的目錄和執行的查詢清單
$ fqltool replay \
--keyspace querylogkeyspace --results /cassandra/fql/logs/results/replay \
--store-queries /cassandra/fql/logs/queries/replay \
-- target 3.91.56.164 \
/tmp/cassandrafullquerylog
--results
和 --store-queries
目錄是選用的,但如果設定了 --store-queries
,則也必須設定 --results
。--target
指定要重播日誌的節點。
-
使用
DESCRIBE KEYSPACES
指令檢查鍵空間是否已重播並再次存在
cqlsh:querylogkeyspace> DESC KEYSPACES;
system_schema system system_distributed system_virtual_schema
system_auth querylogkeyspace system_traces system_views