分布式缓存已经成为了互联网架构的基石,其重要性不言而喻,而且大厂面试也是必考内容,本篇就重点来谈谈分布式缓存@mikechen
为什么要使用分布式缓存
高并发环境下,例如典型的淘宝双11秒杀,几分钟内上亿的用户涌入淘宝。
这个时候如果访问不加拦截,让大量的读写请求涌向数据库,由于磁盘的处理速度与内存显然不在一个量级,服务器马上就要宕机。
缓存可以将经常读取的数据存储在快速的内存中,从而避免了频繁访问慢速的后端数据库。
这样可以大幅减少数据库的负载,加快数据访问速度,提升应用程序的响应性能和吞吐量。
除了提升性能之外,分布式缓存还可以水平扩展。
即通过添加更多缓存节点,来应对不断增长的数据访问需求。
所以,分布式缓存技术就诞生了。
分布式缓存应用场景
特别是在大规模和高并发的应用程序中,都是典型的分布式缓存应用场景
1.热门数据
比如:网站首页、热门商品、热门文章等,可以将其缓存在分布式缓存中,避免每次请求都要重新生成或访问数据库,从而提高响应速度。
2.分布式session
对于需要维护用户会话状态的应用程序,可以将用户会话数据缓存起来。
3. 分布式锁
分布式缓存可以用来实现分布式锁,Redis就经常涉及。
4.页面缓存
比如HTML、CSS和图片等信息。
分布式缓存比较:Memcache VS Redis
Memcache和Redis都是流行的分布式缓存解决方案,它们都可以用于加速应用程序的数据读取,并降低数据库的负载。
下面是两者的核心区别点:
1.数据结构支持
Memcache:它是一个简单的键值存储系统,支持字符串类型的值。
Redis:它是一个高级的键值存储系统,支持多种数据结构。如:字符串、列表、集合、有序集合、哈希等,这使得Redis在一些场景下更为灵活。
2.持久化
Memcache:不支持数据持久化,一旦重启或崩溃,数据将会丢失。
Redis:支持持久化选项,可以将数据存储在硬盘上,保证数据的持久性。Redis提供了3种持久化方式:RDB快照和AOF日志,以及RDB快照和AOF的混合版。
3.内存管理
Memcache:使用Slab Allocation,预先分配一系列大小固定的组,然后根据数据大小选择最合适的块存储,避免了内存碎片。
Redis:使用更复杂的内存管理机制,可以有效地优化内存使用,并支持更多的数据结构,但在一些情况下可能会消耗更多内存。
4.发布/订阅功能
Memcache:不支持发布/订阅模式。
Redis:支持发布/订阅功能,可以用于实现实时消息传递和事件通知。
5.复制和高可用性
Memcache:不支持数据复制,因此在节点发生故障时可能会导致数据丢失。
Redis:支持主从复制,可以设置多个从节点来复制主节点的数据,提高了高可用性。当主节点故障时,可以自动切换到从节点以保证服务的可用性。
6.集群方案
Redis集群解决方式也优于Memcache,Memcache在客户端一致性hash的集群解决方案,Redis采用无中心的服务器端集群解决方案。
分布式缓存选型总结
由于Redis更好的支持持久化、集群部署,以及支持更加丰富的数据结构,综上所述选择Redis会更优。
分布式缓存的常见问题和挑战
1.缓存雪崩
缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。
2.缓存穿透
缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。
3.缓存预热
缓存预热这个应该是一个比较常见的概念,相信很多小伙伴都应该可以很容易的理解,缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!
4.缓存更新
除了缓存服务器自带的缓存失效策略之外,我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种:
(1)定时去清理过期的缓存;
(2)当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。
两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!具体用哪种方案,大家可以根据自己的应用场景来权衡。
5.缓存降级
当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。
降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。
在进行降级之前要对系统进行梳理,看看系统是不是可以丢卒保帅;从而梳理出哪些必须誓死保护,哪些可降级;比如可以参考日志级别设置预案:
(1)一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级;
(2)警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警;
(3)错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的最大阀值,此时可以根据情况自动降级或者人工降级;
(4)严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级。
作者简介
陈睿|mikechen,10年+大厂架构经验,BAT资深面试官,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注作者「mikechen」公众号,获取更多技术干货!
后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》,后台回复【面试】即可获取《史上最全阿里Java面试题总结》