分布式系统架构8:分布式缓存

本文涉及的产品
可观测监控 Prometheus 版,每月50GB免费额度
应用实时监控服务-用户体验监控,每月100OCU免费额度
应用实时监控服务-应用监控,每月50GB免费额度
简介: 本文介绍了分布式缓存的理论知识及Redis集群的应用,探讨了AP与CP的区别,Redis作为AP系统具备高性能和高可用性但不保证强一致性。文章还讲解了透明多级缓存(TMC)的概念及其优缺点,并详细分析了memcached和Redis的分布式实现方案。此外,针对缓存穿透、击穿、雪崩和污染等常见问题提供了应对策略,强调了Cache Aside模式在解决数据一致性方面的作用。最后指出,面试中关于缓存的问题多围绕Redis展开,建议深入学习相关知识点。

这是小卷对分布式系统架构学习的第11篇文章,今天了解分布式缓存的理论知识以及Redis集群。

分布式缓存也是面试常见的问题,通常面试官会问为什么要用缓存,以及用的Redis是哪种模式,用的过程中遇到哪些问题这些

1. AP还是CP

Redis 集群就是典型的 AP 式,它具有高性能、高可用等特点,但它却并不保证强一致性。

而能够保证强一致性的 ZooKeeper、Doozerd、Etcd 等框架,吞吐量比不过Redis,通常不会用作“缓存框架”,而是作为通知、协调、队列、分布式锁等使用

2.透明多级缓存TMC

实际开发中,同时搭配进程内缓存和分布式缓存,来构成透明多级缓存(Transparent Multilevel Cache,TMC)

多级缓存的查询过程如下图:

分布式缓存1.png

缺点:代码侵入性大,由开发人员维护管理

一、二级缓存数据不一致问题解决:

  • 设计原则:变更以分布式缓存中的数据为准,查询以进程内缓存数据优先

3.实现方案

3.1 memcached缓存

在服务端,memcached集群环境实际就是一个个memcached服务器的堆积

cache的分布式主要是在客户端实现,通过客户端的路由处理来达到分布式解决方案的目的。客户端做路由的原理,是在每次存取某key的value时,通过一致性哈希算法把key映射到某台memcached服务器node上。

如下是memcached客户端路由过程:

分布式缓存2.png

3.2 Redis缓存

与memcached客户端支持分布式方案不同,Redis更倾向于在服务端构建分布式存储

分布式缓存3.png

分布式缓存4.png

  • 以Redis集群模式为例,它没有中心节点,具有线性可伸缩的功能。

  • 节点与节点之间通过二进制协议进行通信,节点与客户端之间通过ascii协议进行通信

  • 在数据的放置策略上,Redis Cluster将整个key的数值域分成2的14次方16384个hash槽,每个节点上可以存储一个或多个hash槽,也就是说当前Redis Cluster支持的最大节点数就是16384
  • 总结下:数据hash分布在不同redis节点实例,主/从切换采用Sentinel
  • 写:只会写master Instance,从sentinel获取当前的master instance;
  • 读:从redis node中基于权重选取一个实例读取,失败/超时则轮询其他实例;

要想详细了解redis的面试过程中的问题,可以参考下面的思维导图自行整理:

分布式缓存5.png

4. 缓存风险

4.1 缓存穿透

缓存风险问题也是面试常考的八股文题目,这里还是简单说明下

缓存穿透:查询的数据在数据库里根本不存在,缓存里也不会有,这样的请求每次都不会命中缓存,会请求到末端数据库。这种查询不存在数据的现象就是缓存穿透

解决办法:

  • 对业务逻辑本身不能避免的缓存穿透:对返回为空的Key值进行缓存,如果数据库中对该key插入新记录,就需要主动清理缓存的key值。
  • 恶意攻击导致的缓存穿透:缓存之前设置一个布隆过滤器来解决,思路就是判断请求的数据是否存在,布隆过滤器可以判断某个元素是否在集合中

4.2 缓存击穿

概念:单个热点key失效,在失效的那一刻,同时有大量请求打到DB上,造成数据库压力剧增的情况

解决办法:

  • 设置热点key不过期定时任务更新缓存或者设置互斥锁,当请求过来时,发现缓存不存在数据时,就给当前请求加锁,后面的请求等待或者返回,当从数据库中拿出来放到缓存中时,就可以释放锁资源。

4.3 缓存雪崩

概念:多个热点key缓存失效,大量的key设置了相同的过期时间、导致缓存在同一时间全部失效,造成瞬时DB请求量大、压力剧增。

解决办法:

  • 存数据的过期时间设置随机,防止同一时间大量数据过期现象发生
  • 启用透明多级缓存,多个服务节点因为加载一级缓存的时间不一样,也能分散过期时间

4.4 缓存污染

概念:缓存中的数据与真实数据源中的数据不一致的现象

解决办法:

使用更新缓存时遵循的设计模式,如:Cache Aside,Read/Write Through,Write Behind Caching这些

Cache Aside模式的工作方式:

  • 读数据时,先读缓存,如缓存中没有,则读数据库,再将数据写入缓存中;
  • 写数据时,先写数据库,然后失效缓存(删除缓存数据);

面试可能遇到的两个关于Cache Aside的问题:

1.更新先后顺序,为什么先更新数据库再删除缓存?

  • 假设先删除缓存再更新数据库,会有一段时间是缓存已删除,数据库未更新的情况。这时如果有请求进来,缓存中没查到,就会查数据库中旧的数据,再放到缓存里。造成问题就是:数据库已经是最新数据,缓存中还是旧的,不一致的问题;

2.为什么是删除缓存,而不是更新缓存?

  • 和上面一样,更新过程中,如果有其他更新请求进来更新数据库,缓存就会面临多次修改赋值的复杂时序问题。所以直接删除缓存就行。

总结:本文只写了一些关于分布式缓存的简单理论内容,实际面试时大多围绕redis进行提问,下次再写关于redis的相关内容

相关文章
|
15天前
|
消息中间件 算法 调度
分布式系统学习10:分布式事务
本文是小卷关于分布式系统架构学习系列的第13篇,重点探讨了分布式事务的相关知识。随着业务增长,单体架构拆分为微服务后,传统的本地事务无法满足需求,因此需要引入分布式事务来保证数据一致性。文中详细介绍了分布式事务的必要性、实现方案及其优缺点,包括刚性事务(如2PC、3PC)和柔性事务(如TCC、Saga、本地消息表、MQ事务、最大努力通知)。同时,还介绍了Seata框架作为开源的分布式事务解决方案,提供了多种事务模式,简化了分布式事务的实现。
39 5
|
19天前
|
NoSQL 关系型数据库 MySQL
分布式系统学习9:分布式锁
本文介绍了分布式系统中分布式锁的概念、实现方式及其应用场景。分布式锁用于在多个独立的JVM进程间确保资源的互斥访问,具备互斥、高可用、可重入和超时机制等特点。文章详细讲解了三种常见的分布式锁实现方式:基于Redis、Zookeeper和关系型数据库(如MySQL)。其中,Redis适合高性能场景,推荐使用Redisson库;Zookeeper适用于对一致性要求较高的场景,建议基于Curator框架实现;而基于数据库的方式性能较低,实际开发中较少使用。此外,还探讨了乐观锁和悲观锁的区别及适用场景,并介绍了如何通过Lua脚本和Redis的`SET`命令实现原子操作,以及Redisson的自动续期机
73 7
|
24天前
|
存储 缓存 安全
分布式系统架构7:本地缓存
这是小卷关于分布式系统架构学习的第10篇文章,主要介绍本地缓存的基础理论。文章分析了引入缓存的利弊,解释了缓存对CPU和I/O压力的缓解作用,并讨论了缓存的吞吐量、命中率、淘汰策略等属性。同时,对比了几种常见的本地缓存工具(如ConcurrentHashMap、Ehcache、Guava Cache和Caffeine),详细介绍了它们的访问控制、淘汰策略及扩展功能。
57 6
|
27天前
|
存储 关系型数据库 分布式数据库
[PolarDB实操课] 01.PolarDB分布式版架构介绍
《PolarDB实操课》之“PolarDB分布式版架构介绍”由阿里云架构师王江颖主讲。课程涵盖PolarDB-X的分布式架构、典型业务场景(如实时交易、海量数据存储等)、分布式焦点问题(如业务连续性、一致性保障等)及技术架构详解。PolarDB-X基于Share-Nothing架构,支持HTAP能力,具备高可用性和容错性,适用于多种分布式改造和迁移场景。课程链接:[https://developer.aliyun.com/live/253957](https://developer.aliyun.com/live/253957)。更多内容可访问阿里云培训中心。
[PolarDB实操课] 01.PolarDB分布式版架构介绍
|
4月前
|
NoSQL Java Redis
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
Redis分布式锁在高并发场景下是重要的技术手段,但其实现过程中常遇到五大深坑:**原子性问题**、**连接耗尽问题**、**锁过期问题**、**锁失效问题**以及**锁分段问题**。这些问题不仅影响系统的稳定性和性能,还可能导致数据不一致。尼恩在实际项目中总结了这些坑,并提供了详细的解决方案,包括使用Lua脚本保证原子性、设置合理的锁过期时间和使用看门狗机制、以及通过锁分段提升性能。这些经验和技巧对面试和实际开发都有很大帮助,值得深入学习和实践。
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
|
2天前
|
缓存 NoSQL 中间件
Redis,分布式缓存演化之路
本文介绍了基于Redis的分布式缓存演化,探讨了分布式锁和缓存一致性问题及其解决方案。首先分析了本地缓存和分布式缓存的区别与优劣,接着深入讲解了分布式远程缓存带来的并发、缓存失效(穿透、雪崩、击穿)等问题及应对策略。文章还详细描述了如何使用Redis实现分布式锁,确保高并发场景下的数据一致性和系统稳定性。最后,通过双写模式和失效模式讨论了缓存一致性问题,并提出了多种解决方案,如引入Canal中间件等。希望这些内容能为读者在设计分布式缓存系统时提供有价值的参考。感谢您的阅读!
Redis,分布式缓存演化之路
|
6月前
|
NoSQL Redis
基于Redis的高可用分布式锁——RedLock
这篇文章介绍了基于Redis的高可用分布式锁RedLock的概念、工作流程、获取和释放锁的方法,以及RedLock相比单机锁在高可用性上的优势,同时指出了其在某些特殊场景下的不足,并提到了ZooKeeper作为另一种实现分布式锁的方案。
165 2
基于Redis的高可用分布式锁——RedLock
|
2月前
|
存储 NoSQL Java
使用lock4j-redis-template-spring-boot-starter实现redis分布式锁
通过使用 `lock4j-redis-template-spring-boot-starter`,我们可以轻松实现 Redis 分布式锁,从而解决分布式系统中多个实例并发访问共享资源的问题。合理配置和使用分布式锁,可以有效提高系统的稳定性和数据的一致性。希望本文对你在实际项目中使用 Redis 分布式锁有所帮助。
197 5
|
3月前
|
NoSQL Java 数据处理
基于Redis海量数据场景分布式ID架构实践
【11月更文挑战第30天】在现代分布式系统中,生成全局唯一的ID是一个常见且重要的需求。在微服务架构中,各个服务可能需要生成唯一标识符,如用户ID、订单ID等。传统的自增ID已经无法满足在集群环境下保持唯一性的要求,而分布式ID解决方案能够确保即使在多个实例间也能生成全局唯一的标识符。本文将深入探讨如何利用Redis实现分布式ID生成,并通过Java语言展示多个示例,同时分析每个实践方案的优缺点。
99 8
|
3月前
|
NoSQL Redis
Redis分布式锁如何实现 ?
Redis分布式锁通过SETNX指令实现,确保仅在键不存在时设置值。此机制用于控制多个线程对共享资源的访问,避免并发冲突。然而,实际应用中需解决死锁、锁超时、归一化、可重入及阻塞等问题,以确保系统的稳定性和可靠性。解决方案包括设置锁超时、引入Watch Dog机制、使用ThreadLocal绑定加解锁操作、实现计数器支持可重入锁以及采用自旋锁思想处理阻塞请求。
77 16