缓存是互联网分层架构中非常重要的一部分。通常用于减轻数据库压力,提高系统整体性能,缩短访问时间。有架构师说“缓存是万能的,哪里有问题,可以通过加缓存来优化”,滥用缓存可能会导致一些错误的使用。四种类型的缓存通常被误用。你被抓住了吗?误用一:使用缓存作为服务间传输数据的媒介。如上图所示:(1)Service1和Service2约定key和value,通过缓存传递数据;(2)Service1将数据写入缓存,Service2从缓存中读取数据,达到两个服务通信的目的。该方案存在的问题是:(1)MQ更适合数据管道和数据通知场景;(2)多个服务关联同一个缓存实例会导致服务耦合。误用二:不考虑雪崩就使用缓存。常规的缓存方式如上图所示:(1)服务先读取缓存,缓存命中则返回;(2)缓存未命中,再读取数据库。什么时候会发生雪崩?如果缓存关闭,所有请求将被推送到数据库。如果不提前预估容量,可能会导致数据库被压垮(数据库可能不起来,直到缓存恢复),导致系统整体无法使用。如何应对潜在的雪崩?提前估算容量。如果缓存挂掉了,数据库还是可以处理的,所以可以执行上面的方案。否则,需要进一步设计。更具体地说,有两种常见的解决方案。方案一:高可用缓存如上图所示:使用高可用缓存集群,当一个缓存实例挂掉后,可以自动进行故障转移。方案二:缓存水平切分如上图所示:使用缓存水平切分,一个缓存实例挂掉后,所有的流量都不会压到数据库。误用3:调用者缓存数据。如上图所示:(1)服务提供者缓存,屏蔽调用者获取数据的复杂性(这个没问题);(2)服务调用者也缓存了一条数据,先读取自己的缓存,再决定是否调用该服务(这是有问题的)。该方案存在的问题是:(1)调用方需要注意数据获取的复杂性;(2)更严重的是,服务修改了db中的数据并清除了服务缓存后,很难通知调用者清除其缓存中的数据,导致数据不一致;(3)有人说服务可以通过MQ通知调用方淘汰数据。嗯,下游服务是否依赖于上游调用者?这不是分层架构设计的工作原理。误用4:多个服务共享缓存实例。如上图所示:(1)ServiceA和ServiceB共享一个缓存实例(不通过这个缓存实例来交换数据)。该方案存在的问题是:(1)可能会造成key冲突,会导致彼此的数据被flush掉;画外音:服务A和服务B可能需要提前约定密钥,保证不冲突。常见的约定方式是使用namespace:key的方式来做key。(2)不同服务对应的数据量不同,吞吐量不同。共享一个实例很容易导致一个服务挤占另一个服务的热点数据;(3)共享一个实例会导致服务之间的耦合,与微服务架构“数据库,私有缓存”的设计原则相违背;建议的玩法如下:如上图所示:每个服务将自己的数据存储私有化,对上游屏蔽掉底层的复杂性。总结使用缓存的技巧:(1)服务之间不要通过缓存传递数据;(2)如果缓存挂了,可能会引起雪崩。这时候应该做高可用缓存或者水平切分;(3)调用者不宜单独使用缓存来存储服务的底层数据,容易出现数据不一致和反向依赖;(4)针对不同的服务,缓存实例需要垂直拆分。这些坑你踩过吗?【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文
