Apache Kudu 插入速度慢,排队时间长
Apache Kudu slow insert, high queuing time
我一直在使用 Spark Data Source 从 Parquet 写入 Kudu,写入性能很糟糕:大约 12000 行/秒。每行大约 160 个字节。
我们有 7 个 kudu 节点,每个 24 个核心 + 64 GB RAM + 每个 12 个 SATA 磁盘。 None 的资源似乎是瓶颈:tserver cpu usage ~3-4 core, RAM 10G, disk congestion.
我仍然看到大部分时间写请求都卡在队列中。任何想法表示赞赏。
W0811 12:34:03.526340 7753 rpcz_store.cc:251] Call kudu.tserver.TabletServerService.Write from 10.60.170.18:10000 (ReqId={client: 81ae6f3c6e1b4d9493ea95f87ccd1dfa, seq_no=9365, attempt_no=1}) took 13255ms (client timeout 10000).
W0811 12:34:03.526489 7753 rpcz_store.cc:255] Trace:
0811 12:33:50.270477 (+ 0us) service_pool.cc:163] Inserting onto call queue
0811 12:33:50.270497 (+ 20us) service_pool.cc:222] Handling call
0811 12:34:03.526316 (+13255819us) inbound_call.cc:157] Queueing success response
Related trace 'txn':
0811 12:34:03.328337 (+ 0us) write_transaction.cc:101] PREPARE: Starting
0811 12:34:03.328563 (+ 226us) write_transaction.cc:268] Acquiring schema lock in shared mode
0811 12:34:03.328564 (+ 1us) write_transaction.cc:271] Acquired schema lock
0811 12:34:03.328564 (+ 0us) tablet.cc:400] PREPARE: Decoding operations
0811 12:34:03.328742 (+ 178us) tablet.cc:422] PREPARE: Acquiring locks for 24 operations
0811 12:34:03.447163 (+118421us) lock_manager.cc:377] Waited 118408us for lock on <redacted>
0811 12:34:03.447203 (+ 40us) tablet.cc:426] PREPARE: locks acquired
0811 12:34:03.447203 (+ 0us) write_transaction.cc:126] PREPARE: finished.
0811 12:34:03.447361 (+ 158us) write_transaction.cc:136] Start()
0811 12:34:03.447366 (+ 5us) write_transaction.cc:141] Timestamp: P: 1533965643563964 usec, L: 6
0811 12:34:03.447674 (+ 308us) log.cc:582] Serialized 64909 byte log entry
0811 12:34:03.449561 (+ 1887us) write_transaction.cc:149] APPLY: Starting
0811 12:34:03.526238 (+ 76677us) tablet_metrics.cc:365] ProbeStats: bloom_lookups=48,key_file_lookups=48,delta_file_lookups=24,mrs_lookups=0
0811 12:34:03.526260 (+ 22us) log.cc:582] Serialized 237 byte log entry
0811 12:34:03.526268 (+ 8us) write_transaction.cc:309] Releasing row and schema locks
0811 12:34:03.526280 (+ 12us) write_transaction.cc:277] Released schema lock
0811 12:34:03.526300 (+ 20us) write_transaction.cc:196] FINISH: updating metrics
Metrics: {"child_traces":[["txn",{"apply.queue_time_us":11,"cfile_cache_hit":205,"cfile_cache_hit_bytes":21900627,"num_ops":24,"prepare.queue_time_us":13057291,"prepare.run_cpu_time_us":1017,"prepare.run_wall_time_us":119378,"raft.queue_time_us":71,"raft.run_cpu_time_us":303,"raft.run_wall_time_us":304,"replication_time_us":2170,"row_lock_wait_count":1,"row_lock_wait_us":118408,"spinlock_wait_cycles":45824}]]}
第一个挑战 是将 23M 行 table 和 200 列提取到 Kudu 中(按主键进行 4 个散列分区)花费了很长时间。准确地说,它花费了惊人的 58 分钟,相当于每秒 63 行。我简直不敢相信 Kudu 这么慢,我们确实仔细检查了安装和配置文档。不幸的是,我们信任默认值,正如我在 Kudu slack 频道上发现的(感谢 Will Berkeley!),有两个参数需要调整。具体来说:
memory_limit_hard_bytes
控制 Kudu 守护进程应使用的内存总量。
maintenance_manager_num
维护线程数,建议设置为磁盘数的1/3,用于Kudu
CDH Kudu 包裹的默认值非常糟糕 - Kudu 受到 1Gb 内存的限制,并且仅使用 1 个维护线程。我们将后一个设置为 4(12 个驱动器/3 个),将前一个设置为 0(动态分配)。 CM 不想为 memory_limit_hard_bytes
接受 0,我们不得不使用 CM 安全阀来覆盖它。完成并重新启动 Kudu 后,我的第一个 23M table 在 240 秒内完成(每秒约 95k 行)——好多了!从 Impala 到 Impala 镶木地板的 CTAS 只用了 60 秒。
原来是因为我们的数据重复了。我们正在使用一个包含大约 120 万行的字段,这些行具有与 Kudu 中的主键相同的值(这是一个空字符串)。所以 Kudu 更新了同一个密钥 120 万次,每次都需要获取锁,因此随着时间的推移摄取速度下降。
我们删除了重复的键行,摄取速度提高了 10 倍。
我一直在使用 Spark Data Source 从 Parquet 写入 Kudu,写入性能很糟糕:大约 12000 行/秒。每行大约 160 个字节。
我们有 7 个 kudu 节点,每个 24 个核心 + 64 GB RAM + 每个 12 个 SATA 磁盘。 None 的资源似乎是瓶颈:tserver cpu usage ~3-4 core, RAM 10G, disk congestion.
我仍然看到大部分时间写请求都卡在队列中。任何想法表示赞赏。
W0811 12:34:03.526340 7753 rpcz_store.cc:251] Call kudu.tserver.TabletServerService.Write from 10.60.170.18:10000 (ReqId={client: 81ae6f3c6e1b4d9493ea95f87ccd1dfa, seq_no=9365, attempt_no=1}) took 13255ms (client timeout 10000).
W0811 12:34:03.526489 7753 rpcz_store.cc:255] Trace:
0811 12:33:50.270477 (+ 0us) service_pool.cc:163] Inserting onto call queue
0811 12:33:50.270497 (+ 20us) service_pool.cc:222] Handling call
0811 12:34:03.526316 (+13255819us) inbound_call.cc:157] Queueing success response
Related trace 'txn':
0811 12:34:03.328337 (+ 0us) write_transaction.cc:101] PREPARE: Starting
0811 12:34:03.328563 (+ 226us) write_transaction.cc:268] Acquiring schema lock in shared mode
0811 12:34:03.328564 (+ 1us) write_transaction.cc:271] Acquired schema lock
0811 12:34:03.328564 (+ 0us) tablet.cc:400] PREPARE: Decoding operations
0811 12:34:03.328742 (+ 178us) tablet.cc:422] PREPARE: Acquiring locks for 24 operations
0811 12:34:03.447163 (+118421us) lock_manager.cc:377] Waited 118408us for lock on <redacted>
0811 12:34:03.447203 (+ 40us) tablet.cc:426] PREPARE: locks acquired
0811 12:34:03.447203 (+ 0us) write_transaction.cc:126] PREPARE: finished.
0811 12:34:03.447361 (+ 158us) write_transaction.cc:136] Start()
0811 12:34:03.447366 (+ 5us) write_transaction.cc:141] Timestamp: P: 1533965643563964 usec, L: 6
0811 12:34:03.447674 (+ 308us) log.cc:582] Serialized 64909 byte log entry
0811 12:34:03.449561 (+ 1887us) write_transaction.cc:149] APPLY: Starting
0811 12:34:03.526238 (+ 76677us) tablet_metrics.cc:365] ProbeStats: bloom_lookups=48,key_file_lookups=48,delta_file_lookups=24,mrs_lookups=0
0811 12:34:03.526260 (+ 22us) log.cc:582] Serialized 237 byte log entry
0811 12:34:03.526268 (+ 8us) write_transaction.cc:309] Releasing row and schema locks
0811 12:34:03.526280 (+ 12us) write_transaction.cc:277] Released schema lock
0811 12:34:03.526300 (+ 20us) write_transaction.cc:196] FINISH: updating metrics
Metrics: {"child_traces":[["txn",{"apply.queue_time_us":11,"cfile_cache_hit":205,"cfile_cache_hit_bytes":21900627,"num_ops":24,"prepare.queue_time_us":13057291,"prepare.run_cpu_time_us":1017,"prepare.run_wall_time_us":119378,"raft.queue_time_us":71,"raft.run_cpu_time_us":303,"raft.run_wall_time_us":304,"replication_time_us":2170,"row_lock_wait_count":1,"row_lock_wait_us":118408,"spinlock_wait_cycles":45824}]]}
第一个挑战 是将 23M 行 table 和 200 列提取到 Kudu 中(按主键进行 4 个散列分区)花费了很长时间。准确地说,它花费了惊人的 58 分钟,相当于每秒 63 行。我简直不敢相信 Kudu 这么慢,我们确实仔细检查了安装和配置文档。不幸的是,我们信任默认值,正如我在 Kudu slack 频道上发现的(感谢 Will Berkeley!),有两个参数需要调整。具体来说:
memory_limit_hard_bytes
控制 Kudu 守护进程应使用的内存总量。
maintenance_manager_num
维护线程数,建议设置为磁盘数的1/3,用于Kudu
CDH Kudu 包裹的默认值非常糟糕 - Kudu 受到 1Gb 内存的限制,并且仅使用 1 个维护线程。我们将后一个设置为 4(12 个驱动器/3 个),将前一个设置为 0(动态分配)。 CM 不想为 memory_limit_hard_bytes
接受 0,我们不得不使用 CM 安全阀来覆盖它。完成并重新启动 Kudu 后,我的第一个 23M table 在 240 秒内完成(每秒约 95k 行)——好多了!从 Impala 到 Impala 镶木地板的 CTAS 只用了 60 秒。
原来是因为我们的数据重复了。我们正在使用一个包含大约 120 万行的字段,这些行具有与 Kudu 中的主键相同的值(这是一个空字符串)。所以 Kudu 更新了同一个密钥 120 万次,每次都需要获取锁,因此随着时间的推移摄取速度下降。
我们删除了重复的键行,摄取速度提高了 10 倍。