Cassandra 文档

版本

您正在查看预发布版本的文档。

完整查询日志

Apache Cassandra 4.0 添加了一个新的高性能功能,支持实时查询日志记录 (CASSANDRA-13983)。FQL 适用于生产环境,具有可配置的堆内存和磁盘空间限制,以防止内存不足错误。此功能对于实时流量捕获以及流量回放非常有用。提供的工具可用于调试查询流量和迁移。还添加了新的 nodetool 选项来启用、禁用或重置 FQL,以及一个用于读取和回放二进制日志的新工具。完整查询日志记录 (FQL) 功能使用 Chronicle-Queue 来轮换查询日志。在本文档的剩余部分中,完整查询日志将被称为 **日志**。

FQL 的一些功能包括:

  • 通过异步单线程日志条目写入磁盘,减少了对查询延迟的影响。

  • 堆内存使用量受加权队列限制,可配置的最大权重位于日志记录线程之前。

  • 如果加权队列已满,则生产者可能会被阻塞或样本可能会被丢弃。

  • 磁盘利用率受可配置的大小限制,一旦达到限制,就会删除旧的日志段。

  • 灵活的模式二进制格式,Chronicle-Wire,用于磁盘上的序列化,可以跳过无法识别的字段,添加新的字段并省略旧的字段。

  • 可以使用 JMX 工具 nodetool 启用、禁用或重置(删除磁盘上的数据)。

  • 可以在 cassandra.yaml 文件中或使用 nodetool 配置设置。

  • 引入了新的 fqltool,目前可以将二进制日志 Dump 到可读格式。其他选项包括 ReplayCompare

FQL 记录所有成功的 Cassandra 查询语言 (CQL) 请求,包括修改数据的事件和查询数据的事件。虽然审计日志也包含 CQL 请求,但 FQL 日志只记录 CQL 请求。这种差异意味着 FQL 可用于回放或比较日志,而审计日志则不能。FQL 对于调试、性能基准测试、测试和审计 CQL 查询很有用,而审计日志则对于合规性很有用。

在性能测试中,FQL 在仅 WRITE 的工作负载中似乎没有或几乎没有开销,而在 MIXED 工作负载中则只有很小的开销。

记录的查询信息

查询日志包含:

  • 所有调用的查询

  • 它们被调用的近似时间

  • 绑定通配符值所需的任何参数

  • 所有查询选项

记录器在查询完成后写入单个或批处理的 CQL 查询,因此只记录成功完成的查询。失败或超时查询不会被记录。记录的不同数据取决于查询的类型。

单个 CQL 查询日志条目包含:

  • query - CQL 查询文本

  • queryOptions - 与查询调用相关的选项

  • queryState - 与查询调用相关的时间戳状态

  • queryTimeMillis - 自查询被调用以来,自纪元以来的近似时间(以毫秒为单位)

批处理 CQL 查询日志条目包含:

  • queries - 查询的 CQL 文本

  • queryOptions - 与查询调用相关的选项

  • queryState - 与查询调用相关的时间戳状态

  • batchTimeMillis - 自批处理被调用以来,自纪元以来的近似时间(以毫秒为单位)

  • type - 批处理的类型

  • values - 要绑定为查询参数的值

由于 FQL 由 Binlog 支持,因此性能和占用空间是可预测的,对日志记录记录生产者影响最小。性能安全措施可防止生产者过载日志,使用加权队列在日志记录落后时丢弃记录。单线程异步写入生成日志。Chronicle-Queue 提供了一种轻松的日志滚动方法。

记录的日志信息

FQL 还跟踪有关存储的日志文件的信息:

  • 添加的存储日志文件及其存储影响。如果超过存储限制,则删除它们。

  • 已滚动的 Chronicle-Queue 中的日志文件

  • 已滚动的日志文件中的字节数

日志记录顺序

记录器遵循一个定义明确的事件顺序:

  1. 启动写入日志记录的消费者线程。此操作只能执行一次。

  2. 消费者线程向日志提供记录。如果内存中队列已满,则记录将被丢弃,并且提供将返回 false 值。

  3. 如果接受,则记录将被输入日志。如果内存中队列已满,则放置线程将被阻塞,直到有空间或被中断。

  4. 在线程退出时清理缓冲区。最终确定将再次检查,以确保队列中没有滞留者。

  5. 停止消费者线程。它可以被多次调用。

使用 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

roll_cycle

roll_cycle 定义日志段滚动的频率。支持的值为 HOURLY(默认)、MINUTELYDAILY。例如:roll_cycle: DAILY

block

block 选项指定如果 FQL 落后,FQL 应该阻塞写入还是丢弃日志记录。支持的布尔值为 true(默认)或 false。例如:block: false 以丢弃记录

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

archive_command

archive_command 选项设置在滚动日志文件上执行的用户定义的存档脚本。未定义时,文件将被删除,默认值为 "",然后映射到 org.apache.cassandra.utils.binlog.DeletingArchiver。例如:archive_command: /usr/local/bin/archiveit.sh %path # %path 是正在滚动的文件

max_archive_retries

max_archive_retries 选项设置失败的存档命令的最大重试次数。默认值为 10。例如:max_archive_retries: 10

在启用该功能时,也可以使用nodetool配置 FQL,并且会覆盖cassandra.yaml文件中设置的任何值,如下一节所述。

启用 FQL

使用nodetool enablefullquerylog命令在每个节点上启用 FQL。至少,必须定义日志目录的路径,如果cassandra.yaml文件中未设置log_dir

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

示例

  1. 为了演示 FQL,首先在集群中的一个节点上配置并启用 FQL

$ nodetool enablefullquerylog --path /tmp/cassandrafullquerylog
  1. 现在使用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');
  1. 然后检查数据是否已插入

 cqlsh:querylogkeyspace> SELECT * FROM t;

 id | k | v
 ----+---+------
  0 | 1 | val1

 (1 rows)
  1. 使用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:
  1. 为了演示fqltool replay,首先删除键空间。

cqlsh:querylogkeyspace> DROP KEYSPACE querylogkeyspace;
  1. 现在运行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指定要重放日志的节点。

  1. 使用DESCRIBE KEYSPACES命令检查键空间是否已重放并再次存在

 cqlsh:querylogkeyspace> DESC KEYSPACES;

 system_schema  system  system_distributed  system_virtual_schema
 system_auth    querylogkeyspace  system_traces  system_views