cassandra的cql引起的血案

    源于公司需要把原来存储在redis的数据迁移到cassandra,这部分数据很大(每次插入千万级),但属于可以过期的数据(一般1~2天过期)。

    好了,我们采用DateTieredCompactionStrategy来做压缩存储策略。然后往cassandra里面插入数据5千万,然后设置的TTL为1小时。插入数据完成以后,使用select ttl(field) from table limit 10;查看一下数据以及观察数据还有多久过期。这时候数据很快返回。

  直到所有数据都过了TTL时间,这时候再执行select ttl(field) from table limit 10; 会发现超时。

  一开始觉得奇怪,为什么这时候会超时,于是重复执行此cql,结果当然是继续超时啦。然后还发现cassandra此时变得不稳定,节点间同步都出现问题。

  此处省略了一万字......(各种怀疑、调参、重新测试)

  




  最后回头想,TTL过期后,根据cassandra特性,数据依然保存在磁盘,采用墓碑标记数据已经失效。但是如果执行select ttl(field) from table limit 10; 语句,由于所有分区都没有数据,这相当于需要扫描已经失效的全部磁盘数据。如果多次执行此语句,可能会引发爆内存的问题,然后连锁反应导致节点不同步等问题。

  归根结底,是自己用法不对。解决办法其实也没有很好的办法,可以往这个表插入一部分没有TTL的记录,保证这个表一直有数据,这样select ttl(field) from table limit 10; 语句就会很快命中并返回结果。当然,实际上我们业务上是不应该执行select * from table limit 10; 这种语句的,而是应该带上partitionKey的,如select * from table where partitionKey = ? limit 10; 。上面的语句select * from table limit 10;只是管理员才会用到的(实际上应该谨慎使用)


补充:目前能规避此问题的方法是,控制TTL过期时间点发生在凌晨,并且gc_grace_seconds设置在1小时内,等到compaction操作回收了旧的过期数据后,再执行select * from table limit 10;的话就不会有问题了。这样在正常上班时间,就不会遇到问题。

你可能感兴趣的:(超时,cassandra,TTL,cql)