使用spark连接器提高Cassandra的读取性能 - GC调整,但不仅仅是

时间:2017-12-06 10:13:31

标签: apache-spark cassandra spark-cassandra-connector cassandra-3.0

我在这里写一些关于如何使用spark-cassandra连接器提高分析作业中的读取性能的建议。 我面临的是在对多个分区键执行大量读取时出现的一些超时问题。

在cassandra日志中,这样的超时类似于:

WARN  [ScheduledTasks:1] 2017-12-06 04:31:49,752 MonitoringTask.java:150 - 32 operations timed out in the last 20394 msecs, operation list available at debug log level
DEBUG [ScheduledTasks:1] 2017-12-06 04:31:49,753 MonitoringTask.java:155 - 32 operations timed out in the last 20394 msecs:
SELECT * FROM xyz WHERE ts = 2017-11-10 00:32+1100 LIMIT 5000: total time 15563 msec - timeout 5000 msec
SELECT * FROM xyz WHERE ts = 2017-10-20 00:31+1100 LIMIT 5000: total time 15597 msec - timeout 5000 msec
SELECT * FROM xyz WHERE ts = 2017-10-20 00:49+1100 LIMIT 5000: total time 15596 msec - timeout 5000 msec

群集

我正在使用此配置在群集中运行分析Spark作业:

  • DC1:2个节点,均具有32个内核和64GB内存
  • DC2:具有32和24核的2个节点,均具有64GB RAM

在所有节点上我运行Cassandra和Spark。 作为火花工作,我有一个流媒体工作和分析工作(每天运行一次)。 复制因子是2,每个DC一个。这被配置为每个DC具有每个数据的一个副本。 所有节点都有C * 3.7和Spark 2.1.1,连接器版本2.0.5。

火花流式传输作业负责群集中的写入(它从Flume代理接收数据)。这意味着我的集群整天都有大量的写入工作量,并且每天都会有大量的读取工作量。

表格读取

我正在读取数据的表格有这个模式:

CREATE TABLE xyz (
    ts timestamp,
    f1 text,
    f2 text,
    count counter,
    PRIMARY KEY ((ts), f1, f2)
) WITH CLUSTERING ORDER BY (f1 ASC, f2 ASC)
    AND bloom_filter_fp_chance = 0.01
    AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
    AND comment = ''
    AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
    AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND crc_check_chance = 1.0
    AND dclocal_read_repair_chance = 0.1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair_chance = 0.0
    AND speculative_retry = '99PERCENTILE';

如您所见,分区键是ts,其中每个可能的值代表特定的分钟(例如,2017-12-05 17:42 + 0000)

分析工作

我运行分析作业,每个节点有2个执行程序,每个执行程序4个核心,每个执行程序5GB(总共32个核心和40GB内存)。

分析工作负责从一个C *表读取数据并写入另一个C *表(使用不同的分区键)。

分析作业每24个批次读取12周的数据,每5040分钟读取一次,从而访问5040个分区键。 对于每个批次,我使用5040密钥准备RDD,然后使用repartitionByCassandraReplicajoinWithCassandraTable来确保数据位置。

nodetool tablestatsnodetool tablehistograms我可以看到分区大小平均为422KB。这意味着每批需要读取5040 * 422KB~ = 2GB的(未压缩?)数据。

作业连接到主节点,因为我没有在C *连接器中指定主机。 因此,默认情况下,数据只能从DC1读取。

问题

如果默认的Cassandra Heap空间大小为8GB,则由于C *中的许多读取超时错误,spark作业会失败。 由于FullGC,我能够将这些错误与GC重新暂停相关联。

我调查了很多,我能够排除磁盘访问中的峰值(使用iostat命令)。 在CQLSH中跟踪相同类型的查询我能够看到一个合理的响应时间(10-50ms),同时完成了超过一千个请求。

唯一的问题似乎是垃圾收集器。

我尝试将MAX_HEAP_MEMORY从8GB增加到12GB,然后从12GB增加到16GB。它有所帮助,但仍然看到一些超时:

  • 如上所述,使用8GB,由于有太多超时导致火花错误,作业停止了
  • 12GB的作业在48分钟内完成,由于GC只能在Cassandra日志中显示,因此大约有15-20次超时(对火花作业没有影响)
  • 16GB的工作在41分钟内完成,仍然由于GC(大约10个案例)的一些超时

第一个问题:根据DC之间的延迟(< ; 3ms)?

这将减少DC1上节点的压力,因为读取将分布在4个节点而不是2个节点上。

第二个问题:考虑到数据写入表格的方式,我可能决定将压缩策略更改为spark.cassandra.connection.factory。改变压实策略会有用吗?

这在生产集群中是一项代价高昂的操作,因此我希望能够合理地确定它是有益的。 有关信息,我可以看到不同节点上访问的SSTable数量在50%百分位数的5到12之间,7%和14%用于99%,7-14再次作为最大值(来自DateTieredCompactionStrategy

第三个问题:我还缺少另一个优化点吗?

0 个答案:

没有答案