缓存一致性问题当数据时效性要求高时,需要保证缓存中的数据与数据库中的数据一致,同时也需要保证缓存节点和副本中的数据也保持一致,不能有出入。这个更依赖于缓存的过期和更新策略。一般当数据发生变化时,主动更新缓存中的数据或者移除相应的缓存。缓存并发问题缓存过期后,会尝试从后端数据库中获取数据,这是一个似是而非的过程。但是在高并发场景下,可能会有多个请求同时从数据库获取数据,对后端数据库造成巨大的冲击,甚至会造成“雪崩”现象。另外,当一个缓存key在更新的时候,也有可能被大量的请求获取到,也会造成一致性问题。那么如何避免类似的问题呢?我们会想到一种类似于“锁”的机制。在缓存更新或过期的情况下,先尝试获取锁,更新或从数据库获取完成后再释放锁。其他请求只需要牺牲一定的等待时间即可。继续直接从缓存中获取数据。缓存穿透问题缓存穿透有的地方也叫“击穿”。很多朋友对缓存穿透的理解是,由于缓存失效或者缓存过期,大量请求穿透到后端数据库服务器,对数据库造成巨大的影响。这其实是一种误解。真正的缓存穿透应该是这样的:在高并发场景下,如果某个key被高并发访问但是没有命中,出于容错的考虑会尝试去后端数据库获取,从而导致大量的请求到达数据库,当key对应的数据本身为空时,这会导致数据库中并发执行很多不必要的查询操作,造成巨大的影响和压力。可以使用以下常用方法来避免缓存传统问题:1.缓存空对象。具有空查询结果的对象也被缓存。如果是集合,可以缓存一个空集合(非空)。如果是缓存单个对象,可以通过字段标识符来区分。这可以防止请求渗透到后端数据库。同时,还需要保证缓存数据的时效性。这种方法实现成本较低,更适合命中率不高但可能更新频繁的数据。2.单独的过滤进程存储所有对应数据可能为空的key,拦截在其之前的请求,避免请求穿透到后端数据库。这种方法实现起来比较复杂,更适合命中率低但更新不频繁的数据。缓存抖动问题缓存抖动问题在某些地方可能被称为“缓存抖动”。它可以看作是一种比“雪崩”更温和的故障,但也会在一段时间内对系统造成震荡和性能影响。一般是缓存节点故障引起的。业界推荐的方法是使用一致性Hash算法来解决问题。缓存雪崩现象缓存雪崩是指由于缓存的原因,大量请求到达后端数据库,导致数据库崩溃,整个系统崩溃,发生灾难。造成这种现象的原因有很多。上面提到的“缓存并发”、“缓存穿透”、“缓存抖动”等问题实际上可能会导致缓存雪崩。这些问题也可能被恶意行为者利用。另一种情况,比如在某个时间点,系统预加载的缓存周期性失效,也可能造成雪崩。为了避免这种周期性失效,可以设置不同的过期时间,错开缓存过期时间,从而避免缓存集中失效。从应用架构的角度,我们可以通过限流、降级、熔断等手段来降低影响,也可以通过多级缓存来避免此类灾难。此外,从整个研发系统流程来看,应加强压力测试,尽量模拟真实场景,尽早暴露问题,以防万一。无底缓存现象这个问题是由Facebook的工作人员提出来的。2010年左右,Facebook拥有3,000个memcached节点,缓存了数千GB的内容。他们发现了一个问题——memcached的连接频率和效率下降,所以他们增加了memcached节点。添加后,他们发现连接频率导致的问题依然存在,并没有改善,这就是所谓的“无底洞现象”。目前,数据库、缓存、Nosql、搜索中间件等主流技术栈都支持“分片”技术,以满足“高性能、高并发、高可用、可扩展”的需求。有的在客户端通过Hash取模(或一致性Hash)映射到不同的实例,有的在客户端通过范围值映射。当然也有一些是在服务器端进行的。但是,每个操作可能需要与不同节点进行网络通信才能完成。实例节点越多,开销越大,对性能的影响也越大。主要可以从以下几个方面来避免和优化:1.数据分布方式有些业务数据可能适合Hash分布,有些业务适合范围分布,可以在一定程度上避免网络IO开销。2、IO优化可以充分利用连接池、NIO等技术,尽可能减少连接开销,增强并发连接能力。3、数据访问方式一次获取大数据集,多次获取小数据集的网络IO开销会更小。当然,缓存无底洞的现象并不常见。在绝大多数公司,可能根本不会遇到。根据访问方式**,一次获取大数据集比多次获取小数据集网络IO开销要小。当然,缓存无底洞的现象并不常见。在绝大多数公司,可能根本不会遇到。高并发场景下缓存的常见问题你了解够了吗?
