cassandra 使用IN运算符查询会导致NoHostAvailable,ConnectionBusy“主机过载”

omqzjyyz  于 12个月前  发布在  Cassandra
关注(0)|答案(1)|浏览(185)

我们尝试使用IN查询从Cassandra数据库中获取数据,以过滤特定时间段的数据,如下所述:

"SELECT * FROM "+ DATABASES['default']['NAME'] +".perform_stats WHERE device_id IN (" + ','.join(device_id_lst) + " AND created_at <= " + created_at +" and created_at >= " start_time + ";"

但随机观察下面的错误日志。

cassandra.cluster.NoHostAvailable: ('Unable to complete the operation against any hosts', {<Host: host:9042 datacenter1>: ConnectionBusy('Connection host:9042 is overloaded')})
   File "/opt/app-root/lib64/python3.8/site-packages/cassandra/cqlengine/query.py", line 515, in __iter__
   File "/opt/app-root/lib64/python3.8/site-packages/cassandra/cqlengine/query.py", line 472, in _execute_query
   File "/opt/app-root/lib64/python3.8/site-packages/cassandra/cqlengine/query.py", line 404, in _execute
   File "/opt/app-root/lib64/python3.8/site-packages/cassandra/cqlengine/query.py", line 1531, in _execute_statement
   File "/opt/app-root/lib64/python3.8/site-packages/cassandra/cqlengine/connection.py", line 345, in execute
   File "cassandra/cluster.py", line 2618, in cassandra.cluster.Session.execute
   File "cassandra/cluster.py", line 4877, in cassandra.cluster.ResponseFuture.result
cassandra.cluster.NoHostAvailable: ('Unable to complete the operation against any hosts', {<Host: host:9042 datacenter1>: ConnectionBusy('Connection host:9042 is overloaded')})

在单个查询中,我们尝试在15分钟内获取大约10个设备的数据,对于每个设备,我们有4个条目,持续15分钟。因此,每次查询总计约40个条目。但是观察到系统内存缓存消耗急剧增加,尽管其堆内存约为6/8 GB,并且随机观察上述错误。
你可以参考下面的模式

CREATE TABLE sample.perform_stats (
    device_id uuid,
    created_at bigint,
    stats_data text,
    PRIMARY KEY (device_id, created_at)
) WITH CLUSTERING ORDER BY (created_at DESC)
    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';

当前环境的详细信息如下:

CentOS Version: 7.9
Cassandra version: 4.1.0
Java Version: 11.0.18
python Version: 3.6.8
Django: 3.1.4
django-cassandra-engine: 1.6.1
cassandra-driver==3.24.0

我们已经尝试增加内存,并将每个查询的设备数量从2500减少到10个设备。我们还尝试将djangoORM查询替换为CassandraRAW查询。但到目前为止,没有任何好处。
任何人都可以建议什么可以是这个问题的可能原因和方法,以进一步调试,以解决这个问题?

iqih9akk

iqih9akk1#

这是预期的行为。问题是您的查询使集群中的节点过载。
当您在多个分区上使用IN()操作符时,查询的协调器必须发出多个单独的请求来获取所有分区。这是一种非常昂贵的分散-聚集访问模式,这意味着客户端请求在协调器上排队,直到它们的队列填满。
当协调器的队列达到容量时(因为它正在等待其他节点响应多个请求),它不再能够接受新的请求,导致ConnectionBusy错误。它到达了一个点,所有节点都已使其队列达到最大,导致NoHostAvailable异常。
IN()运算符不是为多分区筛选设计的。相反,它应该只用于筛选单个分区内的行(只用于筛选聚类列)。
根据我的经验,在分区键上使用IN()操作符只有在有2个项目要过滤时才有效,最多可能有3个。再多的话,表现就变得非常不可预测了。
如果在分区键上使用了IN()操作符,则表明数据模型不正确。您应该根据应用程序查询对表进行分区。干杯!

相关问题