缓存系统稳定性 - 架构师峰会演讲实录

简介: 缓存系统稳定性 - 架构师峰会演讲实录

前言

大家好!我是万俊峰,go-zero 作者。感谢 ArchSummit 提供这么好的机会来跟大家分享一下 go-zero 的缓存最佳实践。

首先,大家可以想一想:我们在流量激增的情况下,服务端哪个部分最有可能会是第一个瓶颈?我相信大部分人遇到的都会是数据库首先扛不住,量一起来,数据库慢查询,甚至卡死。此时,上层服务有怎么强的治理能力都是无济于事的。

所以我们常说看一个系统架构设计的好不好,很多时候看看缓存设计的如何就知道了。我们曾经遇到过这样的问题,在我加入之前,我们的服务是没有缓存的,虽然当时流量还不算高,但是每天到流量高峰时间段,大家就会特别紧张,一周宕机好几回,数据库直接被打死,然后啥也干不了,只能重启;我当时还是顾问,看了看系统设计,只能救急,就让大家先加上了缓存,但是由于大家对缓存的认知不够以及老系统的混乱,每个业务开发人员都会按照自己的方式来手撕缓存。这样导致的问题就是缓存用了,但是数据七零八落,压根没有办法保证数据的一致性。这确实是一个比较痛苦的经历,应该能引起大家的共鸣和回忆。

然后我把整个系统推倒重新设计了,其中缓存部分的架构设计在其中作用非常明显,于是有了今天的分享。

我主要分为以下几个部分跟大家探讨:

  • 缓存系统常见问题
  • 单行查询的缓存与自动管理
  • 多行查询缓存机制
  • 分布式缓存系统设计
  • 缓存代码自动化实践

缓存系统涉及的问题和知识点是比较多的,我分为以下几个方面来讨论:

  • 稳定性
  • 正确性
  • 可观测性
  • 规范落地和工具建设

由于篇幅太长,本文作为系列文章第一篇,主要跟大家探讨『缓存系统稳定性』

缓存系统稳定性

缓存稳定性方面,网上基本所有的缓存相关文章和分享都会讲到三个重点:

  • 缓存穿透
  • 缓存击穿
  • 缓存雪崩

为什么首先讲缓存稳定性呢?大家可以回忆一下,我们何时会引入缓存?一般都是当DB有压力,甚至经常被打挂的情况下才会引入缓存,所以我们首先就是为了解决稳定性的问题而引入缓存系统的。

缓存穿透

缓存穿透存在的原因是请求不存在的数据,从图中我们可以看到对同一个数据的请求1会先去访问缓存,但是因为数据不存在,所以缓存里肯定没有,那么就落到DB去了,对同一个数据的请求2、请求3也同样会透过缓存落到DB去,这样当大量请求不存在的数据时DB压力就会特别大,尤其是可能会恶意请求打垮(不怀好意的人发现一个数据不存在,然后就大量发起对这个不存在数据的请求)。

go-zero 的解决方法是:对于不存在的数据的请求我们也会在缓存里短暂(比如一分钟)存放一个占位符,这样对同一个不存在数据的DB请求数就会跟实际请求数解耦了,当然在业务侧也可以在新增数据时删除该占位符以确保新增数据可以立刻查询到。

缓存击穿

缓存击穿的原因是热点数据的过期,因为是热点数据,所以一旦过期可能就会有大量对该热点数据的请求同时过来,这时如果所有请求在缓存里都找不到数据,如果同时落到DB去的话,那么DB就会瞬间承受巨大的压力,甚至直接卡死。

go-zero 的解决方法是:对于相同的数据我们可以借助于 core/syncx/SharedCalls 来确保同一时间只有一个请求落到DB,对同一个数据的其它请求等待第一个请求返回并共享结果或错误,根据不同的并发场景,我们可以选择使用进程内的锁(并发量不是非常高),或者分布式锁(并发量很高)。如果不是特别需要,我们一般推荐进程内的锁即可,毕竟引入分布式锁会增加复杂度和成本,借鉴奥卡姆剃刀理论:如非必要,勿增实体。

我们来一起看一下上图缓存击穿防护流程,我们用不同颜色表示不同请求:

  • 绿色请求首先到达,发现缓存里没有数据,就去DB查询
  • 粉色请求到达,请求相同数据,发现已有请求在处理中,等待绿色请求返回,singleflight模式
  • 绿色请求返回,粉色请求用绿色请求共享的结果返回
  • 后续请求,比如蓝色请求就可以直接从缓存里获取数据了

缓存雪崩

缓存雪崩的原因是大量同时加载的缓存有相同的过期时间,在过期时间到达的时候出现短时间内大量缓存过期,这样就会让很多请求同时落到DB去,从而使DB压力激增,甚至卡死。

比如疫情下在线教学场景,高中、初中、小学是分几个时间段同时开课的,那么这时就会有大量数据同时加载,并且设置了相同的过期时间,在过期时间到达的时候就会对等出现一个一个的DB请求波峰,这样的压力波峰会传递到下一个周期,甚至出现叠加。

go-zero 的解决方法是:

  • 使用分布式缓存,防止单点故障导致的缓存雪崩
  • 在过期时间上加上5%的标准偏差,5%是假设检验里P值的经验值(有兴趣的读者可以自行查阅)

我们做个实验,如果用1万个数据,过期时间设为1小时,标准偏差设为5%,那么过期时间会比较均匀的分布在3400~3800秒之间。如果我们的默认过期时间是7天,那么就会均匀分布在以7天为中心点的16小时内。这样就可以很好的防止了缓存的雪崩问题。

未完待续

本文跟大家一起讨论了缓存系统的常见稳定性问题,下一篇我来跟大家一起分析缓存的数据一致性问题。

所有这些问题的解决方法都已包含在 go-zero 微服务框架里,如果你想要更好的了解 go-zero 项目,欢迎前往官方网站上学习具体的示例。

视频回放地址

ArchSummit架构师峰会-海量并发下的缓存架构设计

项目地址

https://github.com/tal-tech/go-zero

相关文章
|
2月前
|
Ubuntu Linux
查看Linux系统架构的命令,查看linux系统是哪种架构:AMD、ARM、x86、x86_64、pcc 或 查看Ubuntu的版本号
查看Linux系统架构的命令,查看linux系统是哪种架构:AMD、ARM、x86、x86_64、pcc 或 查看Ubuntu的版本号
216 3
|
11天前
|
监控 Android开发 iOS开发
深入探索安卓与iOS的系统架构差异:理解两大移动平台的技术根基在移动技术日新月异的今天,安卓和iOS作为市场上最为流行的两个操作系统,各自拥有独特的技术特性和庞大的用户基础。本文将深入探讨这两个平台的系统架构差异,揭示它们如何支撑起各自的生态系统,并影响着全球数亿用户的使用体验。
本文通过对比分析安卓和iOS的系统架构,揭示了这两个平台在设计理念、安全性、用户体验和技术生态上的根本区别。不同于常规的技术综述,本文以深入浅出的方式,带领读者理解这些差异是如何影响应用开发、用户选择和市场趋势的。通过梳理历史脉络和未来展望,本文旨在为开发者、用户以及行业分析师提供有价值的见解,帮助大家更好地把握移动技术发展的脉络。
|
10天前
|
网络协议 安全 中间件
系统架构设计师【第2章】: 计算机系统基础知识 (核心总结)
本文全面介绍了计算机系统及其相关技术,涵盖计算机系统概述、硬件、软件等内容。计算机系统由硬件(如处理器、存储器、输入输出设备)和软件(系统软件、应用软件)组成,旨在高效处理和管理数据。硬件核心为处理器,历经从4位到64位的发展,软件则分为系统软件和应用软件,满足不同需求。此外,深入探讨了计算机网络、嵌入式系统、多媒体技术、系统工程及性能评估等多个领域,强调了各组件和技术在现代信息技术中的重要作用与应用。
21 3
|
22天前
|
Cloud Native Devops 持续交付
探索云原生架构:构建高效、灵活和可扩展的系统
本文将深入探讨云原生架构的核心概念、主要技术以及其带来的优势。我们将从云原生的定义开始,了解其设计理念和技术原则;接着分析容器化、微服务等关键技术在云原生中的应用;最后总结云原生架构如何助力企业实现数字化转型,提升业务敏捷性和创新能力。通过这篇文章,读者可以全面了解云原生架构的价值和应用前景。
|
22天前
|
运维 Cloud Native Devops
云原生架构的崛起与实践云原生架构是一种通过容器化、微服务和DevOps等技术手段,帮助应用系统实现敏捷部署、弹性扩展和高效运维的技术理念。本文将探讨云原生的概念、核心技术以及其在企业中的应用实践,揭示云原生如何成为现代软件开发和运营的主流方式。##
云原生架构是现代IT领域的一场革命,它依托于容器化、微服务和DevOps等核心技术,旨在解决传统架构在应对复杂业务需求时的不足。通过采用云原生方法,企业可以实现敏捷部署、弹性扩展和高效运维,从而大幅提升开发效率和系统可靠性。本文详细阐述了云原生的核心概念、主要技术和实际应用案例,并探讨了企业在实施云原生过程中的挑战与解决方案。无论是正在转型的传统企业,还是寻求创新的互联网企业,云原生都提供了一条实现高效能、高灵活性和高可靠性的技术路径。 ##
29 3
|
24天前
|
缓存 运维 NoSQL
二级缓存架构极致提升系统性能
本文详细阐述了如何通过二级缓存架构设计提升高并发下的系统性能。
|
2月前
|
设计模式 存储 前端开发
揭秘.NET架构设计模式:如何构建坚不可摧的系统?掌握这些,让你的项目无懈可击!
【8月更文挑战第28天】在软件开发中,设计模式是解决常见问题的经典方案,助力构建可维护、可扩展的系统。本文探讨了.NET中三种关键架构设计模式:MVC、依赖注入与仓储模式,并提供了示例代码。MVC通过模型、视图和控制器分离关注点;依赖注入则通过外部管理组件依赖提升复用性和可测性;仓储模式则统一数据访问接口,分离数据逻辑与业务逻辑。掌握这些模式有助于开发者优化系统架构,提升软件质量。
41 5
|
2月前
|
微服务 API Java
微服务架构大揭秘!Play Framework如何助力构建松耦合系统?一场技术革命即将上演!
【8月更文挑战第31天】互联网技术飞速发展,微服务架构成为企业级应用主流。微服务将单一应用拆分成多个小服务,通过轻量级通信机制交互。高性能Java Web框架Play Framework具备轻量级、易扩展特性,适合构建微服务。本文探讨使用Play Framework构建松耦合微服务系统的方法。Play采用响应式编程模型,支持模块化开发,提供丰富生态系统,便于快速构建功能完善的微服务。
37 0
|
2月前
|
消息中间件 Java RocketMQ
微服务架构师的福音:深度解析Spring Cloud RocketMQ,打造高可靠消息驱动系统的不二之选!
【8月更文挑战第29天】Spring Cloud RocketMQ结合了Spring Cloud生态与RocketMQ消息中间件的优势,简化了RocketMQ在微服务中的集成,使开发者能更专注业务逻辑。通过配置依赖和连接信息,可轻松搭建消息生产和消费流程,支持消息过滤、转换及分布式事务等功能,确保微服务间解耦的同时,提升了系统的稳定性和效率。掌握其应用,有助于构建复杂分布式系统。
40 0
|
2月前
|
消息中间件 缓存 Java
如何优化大型Java后端系统的性能:从代码到架构
当面对大型Java后端系统时,性能优化不仅仅是简单地提高代码效率或硬件资源的投入,而是涉及到多层次的技术策略。本篇文章将从代码层面的优化到系统架构的调整,详细探讨如何通过多种方式来提升Java后端系统的性能。通过对常见问题的深入分析和实际案例的分享,我们将探索有效的性能优化策略,帮助开发者构建更高效、更可靠的后端系统。
下一篇
无影云桌面