Cassandra占用了所有磁盘空间

Geo*_*nko 5 cassandra cassandra-2.0

我有一个单节点cassandra集群,我使用当前分钟作为分区键并插入TTL为12小时的行.

我看到一些我无法解释的问题

  1. /var/lib/cassandra/data/<key_space>/<table_name>包含多个文件,其中很多是真的老(旧的方式,然后12小时,像2天)
  2. 当我尝试在cqlsh中执行查询时,我得到了很多日志,似乎表明我的表包含大量的墓碑

日志:

WARN  [SharedPool-Worker-2] 2015-01-26 10:51:39,376 SliceQueryFilter.java:236 - Read 0 live and 1571042 tombstoned cells in <table_name>_name (see tombstone_warn_threshold). 100 columns was requested, slices=[-], delInfo={deletedAt=-9223372036854775808, localDeletion=2147483647}
WARN  [SharedPool-Worker-2] 2015-01-26 10:51:40,472 SliceQueryFilter.java:236 - Read 0 live and 1557919 tombstoned cells in <table_name> (see tombstone_warn_threshold). 100 columns was requested, slices=[-], delInfo={deletedAt=-9223372036854775808, localDeletion=2147483647}
WARN  [SharedPool-Worker-2] 2015-01-26 10:51:41,630 SliceQueryFilter.java:236 - Read 0 live and 1589764 tombstoned cells in <table_name> (see tombstone_warn_threshold). 100 columns was requested, slices=[-], delInfo={deletedAt=-9223372036854775808, localDeletion=2147483647}
WARN  [SharedPool-Worker-2] 2015-01-26 10:51:42,877 SliceQueryFilter.java:236 - Read 0 live and 1582163 tombstoned cells in <table_name> (see tombstone_warn_threshold). 100 columns was requested, slices=[-], delInfo={deletedAt=-9223372036854775808, localDeletion=2147483647}
WARN  [SharedPool-Worker-2] 2015-01-26 10:51:44,081 SliceQueryFilter.java:236 - Read 0 live and 1550989 tombstoned cells in <table_name> (see tombstone_warn_threshold). 100 columns was requested, slices=[-], delInfo={deletedAt=-9223372036854775808, localDeletion=2147483647}
WARN  [SharedPool-Worker-2] 2015-01-26 10:51:44,869 SliceQueryFilter.java:236 - Read 0 live and 1566246 tombstoned cells in <table_name> (see tombstone_warn_threshold). 100 columns was requested, slices=[-], delInfo={deletedAt=-9223372036854775808, localDeletion=2147483647}
WARN  [SharedPool-Worker-2] 2015-01-26 10:51:45,582 SliceQueryFilter.java:236 - Read 0 live and 1577906 tombstoned cells in <table_name> (see tombstone_warn_threshold). 100 columns was requested, slices=[-], delInfo={deletedAt=-9223372036854775808, localDeletion=2147483647}
WARN  [SharedPool-Worker-2] 2015-01-26 10:51:46,443 SliceQueryFilter.java:236 - Read 0 live and 1571493 tombstoned cells in <table_name> (see tombstone_warn_threshold). 100 columns was requested, slices=[-], delInfo={deletedAt=-9223372036854775808, localDeletion=2147483647}
WARN  [SharedPool-Worker-2] 2015-01-26 10:51:47,701 SliceQueryFilter.java:236 - Read 0 live and 1559448 tombstoned cells in <table_name> (see tombstone_warn_threshold). 100 columns was requested, slices=[-], delInfo={deletedAt=-9223372036854775808, localDeletion=2147483647}
WARN  [SharedPool-Worker-2] 2015-01-26 10:51:49,255 SliceQueryFilter.java:236 - Read 0 live and 1574936 tombstoned cells in <table_name> (see tombstone_warn_threshold). 100 columns was requested, slices=[-], delInfo={deletedAt=-9223372036854775808, localDeletion=2147483647}
Run Code Online (Sandbox Code Playgroud)

我尝试了多种压缩策略,多线程压缩,我尝试使用nodetool手动运行压缩,我也尝试用jmx强制进行垃圾收集.

我的一个猜测是压缩不会删除墓碑文件

任何想法如何避免磁盘空间变得太大,我最担心的是空间不足,我宁愿存储更少(通过使ttl更小但目前没有帮助)

Jim*_*yer 3

当您使用分钟作为分区键时,我假设您使用时间戳作为每个分区内的集群列,并且在执行插入时使用 12 小时的 TTL。这将在每个分区中建立逻辑删除,因为您永远不会删除整行(即一整分钟的分区)。

假设您的键空间称为 k1,表称为 t2,那么您可以运行:

nodetool flush k1 t2
nodetool compact k1 t2
sstable2json /var/lib/cassandra/data/k1/t2/k1-t2-jb-<last version>-Data.db
Run Code Online (Sandbox Code Playgroud)

然后你会看到像这样的所有墓碑(标有“d”表示已删除):

{"key": "00000003","columns": [["4:","54c7b514",1422374164512000,"d"], ["5:","54c7b518",1422374168501000,"d"], ["6:","54c7b51b",1422374171987000,"d"]]}
Run Code Online (Sandbox Code Playgroud)

现在,如果您删除该行(即从 k1.t2 其中 key=3 删除;),然后再次执行刷新、压缩和 sstable2json,您将看到它更改为:

{"key": "00000003","metadata": {"deletionInfo": {"markedForDeleteAt":1422374340312000,"localDeletionTime":1422374340}},"columns": []}
Run Code Online (Sandbox Code Playgroud)

所以你会看到所有的墓碑都消失了,Cassandra 只需记住整行在某个时间被删除,而不是该行的一小部分在某个时间被删除。

消除墓碑的另一种方法是截断整个表。当您这样做时,Cassandra 只需记住整个表在某个时间被截断,因此不再需要保留该时间之前的逻辑删除(因为逻辑删除用于告诉其他节点某些数据已被删除,并且如果你可以说整个表在时间 x 被清空,那么之前的细节就不再重要了)。

那么你如何将其应用到你所问的情况中呢?那么,您可以使用小时和分钟作为分区键,然后每小时运行一次 cron 作业来删除 13 小时前的所有行。然后在下一次压缩时,该分区的所有墓碑都将被删除。

或者每小时保留一个单独的表,然后使用 cron 作业每小时截断 13 小时前的表。

有时有用的另一个策略是“重用”集群键。例如,如果您每秒插入一次数据,则可以使用时间模 60 秒作为集群键,而不是使用高分辨率时间戳作为集群键,并将更唯一的时间戳保留为数据字段。因此,在每分钟分区内,您都会将昨天的逻辑删除(或过时的信息)更改回今天的活动行,然后您就不会在很多天内积累逻辑删除。

希望这能为您提供一些尝试的想法。通常,当您遇到逻辑删除问题时,这表明您需要重新考虑您的架构。