缓存是互联网分层架构中非常重要的一部分。通常用于减轻数据库压力,提高系统整体性能,缩短访问时间。有架构师说“缓存是万能的,哪里有问题,可以通过加缓存来优化”,滥用缓存可能会导致一些错误的使用。缓存,你真的用对了吗?误用1:使用缓存作为服务间传输数据的媒介,如上图所示:服务1和服务2约定key和value,通过缓存传输数据。服务1将数据写入Cache,服务2从缓存中读取数据,达到两个服务通信的目的。该方案存在的问题是:数据管道,数据通知场景,MQ更适合多个服务关联同一个缓存实例,会导致误用服务耦合。:使用缓存不考虑雪崩的常规缓存方式,如上图:服务先读取缓存,如果缓存***返回缓存不***,什么时候会发生雪崩数据库被再次读取?答:如果缓存宕机,所有请求如果没有提前预估容量,可能会导致数据库不堪重负(数据库可能无法起床,直到缓存恢复),导致系统整体无法服务.如何应对潜在的雪崩?答:提前做容量预估。如果缓存宕机了,数据库还是可以处理的,所以可以执行上面的方案。否则,需要进一步设计。常见方案一:高可用缓存如上图所示:使用高可用缓存集群,一个缓存实例挂掉后,可以自动进行故障转移。常见方案二:缓存水平切分如上图所示:使用缓存水平切分,当某个缓存实例宕机后,不会将所有流量推送到数据库。误用3:调用者缓存数据如上图:服务提供者缓存从调用者那里获取数据的复杂性(这个没问题)服务调用者也缓存了一段数据,先读取自己的缓存,再决定是否要callService(这个有问题)这个方案的问题是:调用者需要注意数据获取的复杂性。服务修改了db中的数据,服务缓存清除后,很难通知调用者清除缓存中的数据。这会导致数据不一致。有人说服务可以通过MQ通知调用方淘汰数据。那么,下游服务是否依赖于上游调用者?分层架构设计不是这样的误用。服务A和服务B共享一个缓存实例(不通过这个缓存实例来交换数据)。这个方案的问题是可能会造成key冲突,flush彼此的数据画外音:服务A和服务B可能需要提前约定好key,保证不冲突,常见的约定是使用namespace:key作为关键。不同的业务对应的数据量和吞吐量是不同的。共享一个实例很容易导致一个服务挤出另一个服务的热点数据来共享一个实例,从而导致服务之间的耦合,这有别于微服务架构的“数据库、缓存”和“私有”的设计原则与建议的玩法相反:如上图所示:每个服务将自己的数据存储私有化,对上游屏蔽底层的复杂性。总结缓存使用技巧:服务之间不要通过缓存传递数据。如果缓存宕机,可能会导致雪崩。这时候就需要一个高可用的缓存,或者调用者不要单独使用缓存来存储服务的底层数据。容易出现数据不一致和对不同服务的反向依赖。缓存实例需要垂直拆分。
