什么是一个多级缓存系统?它有什么用?我们又如何设计一个多级缓存系统?

图片来自 Pexels

所谓多级缓存系统,就是指在一个系统的不同的架构层级进行数据缓存,以提升访问效率。

我们都知道,一个缓存系统,它面临着许多问题,比如缓存击穿,缓存穿透,缓存雪崩,缓存热点等等问题,那么,对于一个多级缓存系统,它有什么问题呢?

有如下几个:

  • 缓存热点:多级缓存系统大多应用在高并发场景下,所以我们需要解决热点 Key 问题,如何探测热点 Key?
  • 数据一致性:各层缓存之间的数据一致性问题,如应用层缓存和分布式缓存之前的数据一致性问题。
  • 缓存过期:缓存数据可以分为两大类,过期缓存和不过期缓存?如何设计,如何设计过期缓存?

在这之前,我们先看看一个简单的多级缓存系统的架构图:

整个多级缓存系统被分为三层:

  • 应用层 Nginx 缓存
  • 分布式 Redis 缓存集群
  • Tomcat 堆内缓存

整个架构流程如下:当接收到一个请求时,首先会分发到 Nginx 集群中,这里可以采用 Nginx 的负载均衡算法分发给某一台机器,使用轮询可以降低负载,或者采用一致性 Hash 算法来提升缓存命中率。

当 Nginx 层没有缓存数据时,会继续向下请求,在分布式缓存集群中查找数据,如果缓存命中,直接返回(并且写入 Nginx 应用缓存中),如果未命中,则回源到 Tomcat 集群中查询堆内缓存。

在分布式缓存中查询不到数据,将会去 Tomcat 集群中查询堆内缓存,查询成功直接返回(并写入分 Redis 主集群中),查询失败请求数据库;堆内缓存。

如果以上缓存中都没有命中,则直接请求数据库,返回结果,同步数据到分布式缓存中。

在简单了解了多级缓存的基本架构之后,我们就该思考如何解决上面提到的一系列问题。

缓存热点

缓存热点,是一个很常见的问题,比如“某某明星宣布结婚”等等,都可能产生大量请求访问的问题,一个最麻烦也是最容易让人忽视的事情就是如何探测到热点 Key。

在缓存系统中,除了一些常用的热点 Key 外,在某些特殊场合下也会出现大量的热点 Key,我们该如何发现呢?

有以下策略:

  • 数据调研。可以分析历史数据以及针对不同的场合去预测出热点 Key,这种方式虽然不能百分百使得缓存命中,但是却是一种最简单和节省成本的方案。
  • 实时计算。可以使用现有的实时计算框架,比如 Storm、Spark Streaming、Flink 等框架统计一个时间段内的请求量,从而判断热点 Key。或者也可以自己实现定时任务去统计请求量。

这里我们着重讨论一下第二种解决方案,对于热点 Key 问题,当缓存系统中没有发现缓存时,需要去数据库中读取数据。

当大量请求来的时候,一个请求获取锁去请求数据库,其他阻塞,接着全部去访问缓存,这样可能因为一台服务器撑不住从而宕机。

比如正常一台服务器并发量为 5W 左右,产生热点 Key 的时候达到了 10W 甚至 20W,这样服务器肯定会崩。所以我们在发现热点 Key 之后还需要做到如何自动负载均衡。

结合以上问题我们重新设计架构,如下图所示:

我们将整个应用架构分为:

  • 应用层
  • 分布式缓存
  • 系统层
  • 数据层

在应用层,我们采用 Nginx 集群,并且对接实时计算链路,通过 Flume 监控 Nginx 日志,将数据传输到 Kafka 集群中,然后 Flink 集群消费数据进行统计。

如果统计结果为热点 Key,则将数据写入 Zookeeper 的节点中,而应用系统通过监控 Znode 节点,读取热点 Key 数据,去数据库中加载数据到缓存中并且做到负载均衡。

实际上,对于应用系统中的每一台服务器,还需要一层防护机制,限流熔断,这样做的目的是为了防止单台机器请求量过高,使得服务器负载过高,不至于服务器宕机或者大量请求访问数据库。

简单思路就是为每一台服务器设计一个阀值,当请求量大于该值就直接返回用户空白页面或者提示用户几秒后刷新重新访问。

数据一致性

数据一致性问题主要体现在缓存更新的时候,如何更新缓存,保证数据库与缓存以及各层缓存层之间的一致性。

对于缓存更新问题,先写缓存还是先写数据库,这里省略若干字。之前的文章介绍过,有兴趣的读者可以翻阅。

在单层缓存系统中,我们可以先采用删除缓存然后更新数据库的方案来解决其数据一致性问题,那么对于多级缓存呢?

如果使用这种方案,我们需要考虑,如果先删除缓存,那么需要逐层去做删除操作,那么这一系列操作对系统带来的耗时也是很可观的。

如果我们使用分布式事务机制,就需要考虑该不该将写缓存放入事务当中,因为我们更新分布式缓存,需要走网络通信,大量的请求将导致网路抖动甚至阻塞,增加了系统的延迟,导致系统短时间内不可用。

如果我们不将写缓存这一操作放入事务当中,那么可能引起短时间内数据不一致。

这也就是分布式系统的 CAP 理论,我们不能同时达到高可用和一致性。那么该如何抉择呢?

这里我们选择保证系统的可用性,就一个秒杀系统来讲,短暂的不一致性问题对用户的体验影响并不大(当然,这里不涉及支付系统)。

而可用性对用户来说却很重要,一个活动可能在很短的时间内结束,而用户需要在这段时间内抢到自己心仪的商品,所以可用性更重要一些(这里需要根据具体场景进行权衡)。

在保证了系统的可用性的基础上,我们该如何实现呢?如果实时性要求不是很高,我们可以采用全量+增量同步的方式进行。

首先,我们可以按照预计的热点 Key 对系统进行缓存预热,全量同步数据到缓存系统。

接着,在需要更新缓存的时候,我们可以采用增量同步的方式更新缓存。比如我们可以使用阿里 Canal 框架同步 Binlog 的方式进行数据的同步。

缓存过期

缓存系统中的所有数据,根据数据的使用频率以及场景,我们可以分为过期 Key 以及不过期 Key,那么对于过期缓存我们该如何淘汰呢?

下面有常用的几种方案:

  • FIFO:使用 FIFO 算法来淘汰过期缓存。
  • LFU:使用 LFU 算法来淘汰过期缓存。
  • LRU:使用 LRU 算法来淘汰过期缓存。

以上几种方案是在缓存达到最大缓存大小的时候的淘汰策略,如果没有达到最大缓存大小,我们有下面几种方式:

  • 定时删除策略:设置一个定时任务,在规定时间内检查并且删除过期 Key。
  • 定期删除策略:这种策略需要设置删除的周期以及时长,如何设置,需要根据具体场合来计算。
  • 惰性删除策略:在使用时检查是否过期,如果过期直接去更新缓存,否则直接返回。

作者:不清不慎来源:架构师社区

fifo页面置换算法设计思路_千万级并发!如何设计一个多级缓存系统?相关推荐

  1. FIFO页面置换算法详解

    页面置换算法的基本思想: FIFO每次置换最先调入内存的页面,即将内存中等待时间最长的页面进行置换.此算法的适用范围是顺序结构程序. 实现过程 比如有下述页面走向:1, 2, 3, 4, 2, 1, ...

  2. 操作系统之虚拟存储管理 java python 实现 最优(Optimal)置换算法 先进先出(FIFO)页面置换算法 LRU(Least Recently Used)置换算法

    操作系统之虚拟存储管理 实验内容:模拟请求分页虚拟存器管理技术中的硬件地址变换.缺页中断以及页式淘汰算法,处理缺页中断. 实验目的:清楚认识请求分页管理. 最佳(Optimal)置换算法 其所选择的被 ...

  3. 千万级并发!如何设计一个多级缓存系统?

    作者:不清不慎,目前在杭州蘑菇街公司任职,Java大数据开发工程师一枚,热爱研究开源技术! 架构师社区合伙人! 首先我们需要明白,什么是一个多级缓存系统,它有什么用.所谓多级缓存系统,就是指在一个系统 ...

  4. 操作系统页面置换算法之先进先出(FIFO)页面置换算法(C语言实现)

    先进先出(FIFO)页面置换算法 [注]本代码数据及思路方法参考自<计算机操作系统(第四版)>汤小丹等 编著的教材. #include <iostream>int access ...

  5. fifo页面置换算法java_缓存算法(页面置换算法)-FIFO、LFU、LRU

    转自:http://www.cnblogs.com/dolphin0520/ 1.FIFO算法 FIFO(First in First out),先进先出.其实在操作系统的设计理念中很多地方都利用到了 ...

  6. 【操作系统实验】FIFO页面置换算法

    一.实验描述 二.实验程序 #include<stdio.h> void main() {int i,j,k=0;char cc[13];//Y表示发生缺页中断,N表示未发生int a[1 ...

  7. 7-1 页面置换算法--FIFO (50 分)(思路详解)

    一:题目 先初始化页面大小,和物理块数.连续输入页面的逻辑地址,以"-1"作为结束标志,采用FIFO页面置换算法.固定分配局部置换分配策略.输出该页面的页号和页内位移,若该页不在内 ...

  8. 操作系统页面置换算法(opt,lru,fifo,clock)实现

    选择调出页面的算法就称为页面置换算法.好的页面置换算法应有较低的页面更换频率,也就是说,应将以后不会再访问或者以后较长时间内不会再访问的页面先调出. 常见的置换算法有以下四种(以下来自操作系统课本). ...

  9. 【操作系统】FIFO先进先出页面置换算法(C语言实现)

    FIFO页面置换算法,计算缺页率,文末附代码,及例题解析 1.内容 在地址映射过程中,若在页面中发现所要访问的页面不在内存中,则产生缺页中断.当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系 ...

最新文章

  1. 英伟达的STEAL AI让神经网络拥有更好的计算机视觉
  2. 如何计算数据集均值和方差
  3. 如果我的实验室也这样布置,那多好。
  4. DataGridView中的CheckBox
  5. 《零基础》MySQL UNION 操作符(十七)
  6. 逐步回归 图像降维matlab,使用matlab对训练样本图像降维,并对测试图像使用变换矩阵降维并重构...
  7. 【CVPR 2020】Learning RoI Transformer for Oriented Object Detection in Aerial Images
  8. oracle中的存储过程
  9. 109. 有序链表转换二叉搜索树
  10. Android_之动画1
  11. coherence初识
  12. linux 命令汇总(搜索、fdfs、常用命令),虚拟机dump文件
  13. 将rgba图片信息转换为bmp图片文件
  14. 《信息安全技术—个人信息安全影响评估指南》pdf下载
  15. 无法阻止的电竞热潮-用电竞连接世界
  16. Android调用getSimSerialNumber获取iccid不完整(RK3288 7.1.2)
  17. 魅族手机云便签的这些使用小技巧 你都知道吗?
  18. js(76-108)
  19. Error during WebSocket handshake: Unexpected response code: 429
  20. arduino/Mixly使用ZH03BPM2.5传感器

热门文章

  1. 质量审查一体化智能平台 搭建总览图
  2. jmeter 压测 RabbitMQ_单机
  3. (Docker实战) 第3篇:Centos7 拉取和部署Mysql
  4. Oracle查询所有序列;[oracle中如何创建表的自增ID(通过序列);oracle sql语句大全
  5. linux 创建用户和修改新增用户默认的家目录
  6. MybatisPlus_进阶
  7. python的程序格式框架_关于Python程序格式框架的描述,以下选项中错误的是
  8. C语言 va_arg 宏 - C语言零基础入门教程
  9. scala java抽象理解_Scala之类、特质和抽象类
  10. 大学计算机要学多久,大学刚开学要不要带电脑?很多人都很后悔,学长学姐把经验告诉你...