Cassandra 1.1的缓存策略
从0.5和0.6版本开始, Cassandra就提供了主键 缓存和行缓存。在1.1 版本中,Cassandra的核心开发团队重新对缓存策略进行了设计和实现,以提供配置更简单但同时又更高效的缓存效果。
为什么要将缓存集成到数据库内部?
实际上,缓存既可以储存到数据库内部,也可以是外部的独立缓存层。将缓存集成到数据库内部,有下面一些好处:
- 天然具备分布式特性:Cassandra本身就是一个分布式的数据存储系统,所以在其中加入缓存功能也自然而然的成为分布式缓存。你不需要使用像 ketema 这种一致性hash库去实现自己的分布式缓存系统。
- 简化架构:在一个技术架构中,活动组件越多,通常复杂度也越高,出问题的几率也更大。像排查一个分布式缓存系统问题这种事,即使是对经验丰富的运营工程师也是件费劲的活。
- 保持缓存与数据库一致性:如果你采用了外部缓存系统,那么你的客户端在操作数据时,必然会涉及到先后对数据库和缓存进行两次更新操作。这期间无论是你先更新缓存还是数据库,后更新那一个一旦失败,就必然会出现缓存中的数据与数据库中的不一致的问题(更新或者更老)。而这个问题实际上很好解决,通过将缓存集成到数据库中,我们在客户端只需要进行一次对数据库的更新操作,至于缓存和数据的一致性,交给数据库来解决就行了。
- 自动的数据冗余:如果你用Memcached作为独立到数据库的缓存层,那么在Memcached出现故障时,可能读请求就会直接落到数据库上,因为Memcached本身没有缓存冗余存储的功能,导致一个点倒掉缓存就失效了。而如果把缓存集成到数据库中,由于Cassandra本身的分布式特点,其缓存也是分布式冗余到多个节点的,所以节点故障不会导致缓存系统失效。
- 解决数据预热的问题:数据预热是指的在缓存故障重启后,由于缓存中此时空无一物,所以所有请求都会直接落到数据库上,为了防止数据库直接被压崩溃,运营人员通常会人为的控制流量,而结果就是导致大部分的用户故障,需要一段时间等缓存慢慢充满后才能恢复正常服务。这是传统缓存的一个典型问题。而Cassandra的集成缓存会进行定期的落地操作,Cassandra会定期将内部缓存定到磁盘上,这样当故障重启后,我们只需要一次性把原来的缓存镜像加载到内存中就行了,不需要通过用户访问一点点预热缓存。
主键缓存和行缓存
主键缓存就是对Cassandra表的 主键的缓存,主键缓存能够节约内存和CPU时间。但是,如果仅仅是开启主键缓存的话,我们在取具体每一行数据时还是可能会导致磁盘操作。
行缓存类似于传统的Memcached缓存,其机制是,当某一行数据被访问时,将其加载到内存中,这样后续的访问只需要通过内存访问就能拿到这一行数据。
在一般的场景下,你可能会选择开启主键缓存或者行缓存,这样会提高读性能。但是对那种不经常读的表,就可以完全不开启缓存了。
Cassandra1.1中缓存的配置
最主要的缓存设置参数有两个:key_cache_size_in_mb 和 row_cache_size_in_mb,都通过在 cassandra.yaml中进行设置。
与之前版本不同的是,1.1版本中不再需要对每个表单独进行缓存大小的设置,所有缓存都在一个池子里共享内存,Cassandra内部会自动地按使用情况合理分配内存。
而对于行缓存,还有一个 row_cache_provider 参数可以对其具体实现进行控制,当设置其值为 SerializingCacheProvider 时,缓存对内存的使用非常高效(在非 blob密集的情况下,有5到10倍的内存使用率提升),但是如果是更新频繁的应用场景下,其性能会比较糟糕。因为更新操作会导致其将缓存置为失效。而这时候如果使用 ConcurrentLinkedHashCacheProvider 的话会更好,因为它是直接更新缓存的值。
OpsCenter 通过查看缓存的效率,通过来说,缓存达到90%以上的命中率是比较正常的。如果你某个表的行缓存达不到这个数,那么建议你将这个表的行缓存去掉,仅保留主键缓存。这样它原本用在行缓存上的内存就可以被其它命中率更高的表更高效地使用了。
现有问题与未来规划
目前的缓存机制最大的问题是,行缓存是将一行数据直接放到内存中去的。所以对于“找出最近50条数据”这样的查询操作就无能为力了。
幸运的是,这个问题也在解决中,下面两个提案已经在跟进中了。
来源: www.datastax.com
相关文章: |
Cassandra发布0.6.1版本 |
Cassandra 发布 0.6.2 版本 修复bug 20个 |
Cassandra发布新稳定版本:0.6.5 |
cassandra观止 |
Cassandra数据模型 |
无觅 |