cassandra的cql引发的血案

    源于公司须要把原来存储在redis的数据迁移到cassandra,这部分数据很大(每次插入千万级),但属于能够过时的数据(通常1~2天过时)。
redis

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

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

  一开始以为奇怪,为何这时候会超时,因而重复执行此cql,结果固然是继续超时啦。而后还发现cassandra此时变得不稳定,节点间同步都出现问题。
内存

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

  




  最后回头想,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;只是管理员才会用到的(实际上应该谨慎使用)it


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

相关文章
相关标签/搜索