在系统架构中缓存是不可或缺的解决方案,在高访问量系统中使用缓存可以减轻持久层工作负载、网络负载,提高数据获取速度,扩展系统的瓶颈。合理的使用缓存技术能极大提高系统性能,可是不合理的使用下却可能收益甚小更甚者导致系统性能下降、系统功能异常等。以下从几个角度讨论数据缓存使用中的一些经验。

首先,单点缓存与分布式缓存的比较与选择。随着分布式时代的到来类似Redis,Memcached等可以透明使用的缓存方案受到了热捧,但在Memcached有成熟的开源分布式方案前,在Redis3.X正式支持集群前,选择分布式缓存实际上代表要使用不低付费的商业方案,或者自己实现缓存集群的分布计算,对创业团队来说过多的预算与过长的开发时间都是不能接受的,除此之外一个稳定缓存集群的运维工作也是需要消耗大量人力资源的。

所以创业技术团队前期多半使用多个单点的缓存方案过度(例如我们团队前期就选择对每个服务节点对应一个单点缓存),单点缓存从实现上看没有什么技术复杂度,在前期能快速的与已有系统结合极高提升系统读并发性能;可是随着使用场景丰富,单点缓存不能满足状态类缓存在各节点一致性需要,比如session,计数,各种对一致性要求高的场景就不能使用,单点的缓存内存也有物理设备的限制不可能无限增长上限,并且随着服务节点的增加,多个单点缓存对内存资源的利用也显得很低,几乎每个缓存节点都会重复一份缓存,这明显是很不划算的投资,因此单点缓存多适用于缓存不变的应用配置、缓存不变的系统配置、缓存对数据一致性要求不高的数据。

综合考虑,如果是创业团队前期可以考虑直接使用云服务作为缓存容器,方便扩展、省时、省力,在后期各种技术指标更高的情况下再考虑自建分布式缓存系统。因此我们团队也在服务节点不断增加后,实现了新的缓存接口,将适合分布式缓存场景的部分数据缓存迁移到了Memcached协议的云服务上,同时也会保留单点缓存,根据场景综合使用。

在有了缓存容器之后,就是如何使用缓存了,通常系统缓存层在数据持久层之上,由业务层访问缓存层,缓存层没有则访问数据持久层并将数据放入缓存中,方便下次使用。可是并不是所有数据都需要缓存,不常读取的(频率很低)通常不需要缓存、经常变更的不一定需要。获取数据时间阻塞,效率低,重复度高的一般代表要使用缓存了。使用缓存一定要关心命中率,命中率越高代表缓存的效率越高,经常miss的缓存反而适得其反。仅仅为了使用缓存而强行用只不过是一厢情愿的加大内存负载,提高系统复杂度。

在高并发业务中针对不同的业务场景也应该选择合适的缓存算法。比如对分页数据列表,排名类数据,自然访问量密集的数据选择LFU就很合适,总能保持密集访问型数据的高命中率;对于比较平滑的业务则采用LRU通常更合理,可能相对命中率不会特别高不过能够减轻数据库负载,保持系统稳定。缓存算法是个很大的话题,因此不再此深入展开。

另外在读负载很大的系统中,要注意做好系统启动的缓存预热,否则系统启动后数据库服务在瞬间高压下可能直接失去工作能力,对于因为高压瘫痪的系统基本就是恶性循环很难再次正常启动。对自带持久的缓存服务如Redis可以配置本地持久话,避免重启系统后持久层直接受到冲击。对于纯内存缓存服务,可以先模拟真实情况访问实现预热部分缓存再打开系统公网开关。当然最好是保持缓存集群的透明、高可用性、高扩展性。

缓存的加载时机很重要,但同时缓存的淘汰时机也很重要。对于实时性不强的业务,可以先淘汰缓存再写入数据,通常能解决缓存脏数据的问题。但是对于读密集并发高的系统,有可能先淘汰了缓存,写入数据的过程中就有新的请求又将旧数据填充了缓存,导致读到的脏缓存数据,对于类似顶、赞的计数其实是可以容忍的。但是对于时效性稍微强一点功能,比如修改帖子,如果缓存时间是10分钟,那么脏缓存将强占10分钟。所以如果不是写密集的业务,处女座可以选择在写入数据成功后异步淘汰该数据对应的缓存,保证写入成功后读到的是新数据。而对于要求绝对一致性的数据操作,最安全的做法就是在相关业务中避免读取缓存数据,从主数据库直接读取,在业务结束后淘汰缓存。

缓存过期时间的设置也是有很多要注意的,很重要一点就是一定要设置过期时间,缓存并不是持久化的替代方案,要避免长期无用的缓存数据会侵占宝贵的内存空间,导致缓存臃肿低效,设置过期时间可以让无用数据自动被淘汰,小细节却能换来很大的系统收益。对于使用过期淘汰策略的业务,缓存时间长度通常与对应业务数据的更新频率成反比,一段时间内数据更新越少缓存时间可以设置相对较长。所以要根据业务场景不同来调节缓存过期时间。一刀切的使用一个过期时间是不合理的,一股脑的把所有数据都塞进缓存也是不行的。

最后当系统已经进入瓶颈后,需要针对不同业务分开调优缓存,结合对应的系统监控数据与缓存的监控数据多轮多像分析缓存的各个因素对某个业务的影响,这个过程需要不断重复,慢慢的调整各像以达到最大程度的优化,对与以前不合理使用缓存的地方会有大幅的系统性能提升,虽然耗时长、枯燥,但是对于一个庞大的系统来说,一个百分点的系统性能提升也是很可观的。


本文地址
本文采用 知识共享署名 4.0 国际许可协议进行许可,欢迎转载内容,并请注明出处。