缓存的今生今世

缓存是什么

了解缓存,首先要了解内存概念,毕竟缓存离不开内存。

内存又称内部存储器和主存储器(RAM),内存条由内存芯片、电路板、金手指等部分组成。它与CPU之间的连通是通过总线完成,是CPU与外存的连通桥梁。计算机里所有的运算都是有内存的来完成的,即使CPU再快,内存的容量不够和读写速度不行,计算机的性能也大大折扣。

缓存就是存储数据副本或计算结果的组件,以便后续可以更快地访问

缓存的作用

  • 快:减少延时,提升响应时间,提升用户体验
  • 缓解CPU压力
  • 缓解I/O压力

缓存的应用场景

  • 读多写少

    比如基础数据(省份、国家等)

  • 在一定程度容忍弱一致性、数据丢失

    比如电商商品展示,前100个商品信息;短信验证码、...

  • 实时性要求低

  • 访问频率高

    高并发调用、登录页面

常见的缓存

硬件

CPU缓存

缓存行(Cache Line)

缓存基本上来说就是把后面的数据加载到离自己最近的地方,对于 CPU 来说,它是不会一个字节一个字节的加载的

  • Tag: 每条 Cache Line 前都会有一个独立分配的 24 bits来存的 tag,其就是内存地址的前24bits;
  • Index: 内存地址后续的6个bits则是在这一Way的是Cache Line 索引,2^6 = 64 刚好可以索引64条Cache Line;
  • Offset: 再往后的6bits用于表示在Cache Line 里的偏移量
路(Way)

缓存需要把数据放到缓存行里,但要容忍一定的hash冲突,也就出现了 N-Way 关联。也就是把连续的 N 个 Cache Line 绑成一组

缓存一致性协议

MESI协议中每个缓存行都有四个状态,分别是:

E(exclusive)独占

缓存行只在当前缓存中,但是是干净的(clean)-- 缓存数据与主存数据相同。

当别的缓存读取它时,状态变为共享(S);

当前写数据时,变为已修改状态(M)。

M(modified)已修改

缓存行是脏的(dirty),与主存的值不同。如果别的CPU内核要读主存这块数据,该缓存行必须回写到主存,状态变为共享(S)。

S(shared)共享

缓存行也存在于其它缓存中且是干净的。

I(invalid)无效

缓存行是无效的

伪共享

由于不同的数据会存在同一个CacheLine,那么只要这个缓存行的某个数据变化了,那么就是导致这个缓存行的数据失效,这个时候其他CPU Core就会存在Cache miss的情况,需要重新到主存加载新数据,这就是所谓的false share(伪共享)。

GPU缓存

​ GPU 缓存节点直接将缓存的数据路由到系统显卡,以处理、忽略 Maya 依存关系图求值.

数字信号处理器(DSP)缓存

软件

客户端缓存

页面缓存

页面缓存到本地,下次请求不会重复请求相同的资源文件。比如H5通过Mainfest文件来支持离线缓存。

APP缓存

将内容缓存到内存或本地数据库中,如图片、视频上次观看记录等

浏览器缓存

用户返回、回退操作后到内容,都可以通过浏览器缓存技术实现,从而减少页面加载时间和网络带宽的使用。从HTTP1.0到HTTP2.0,其引进了状态缓存、强缓存、协商缓存都是Http缓存机制。Http1.1通过引入e-tag标签、expires、cache-control来支持浏览器缓存。

  • 强制缓存:缓存在有效期内,无需经过任何请求,一直存在。通过HTTP header实现:expires和cache-control参数控制。当输入地址、链接跳转、前进后退等,均可生效,当用户主动刷新页面(F5)时会自动消失。
  • 协商缓存:一种基于变化检测的缓存机制。通过HTTP header实现:基于最后修改时间Last-modified是否变化和资源唯一标识Etag是否变化来实现的。当输入地址、链接跳转、前进后退及用户吧主动刷新页面(F5)也会生效,当用户强制刷新页面(CTRL+F5)会自动消失。

网络缓存

正向代理
  • 含义:即客户端的代理,有自己去配置代理服务器地址,去请求目标服务器,客户端能感知到目标服务器的存在。

  • 常用场景:翻墙、VPN、静态资源缓存

反向代理
  • 含义: 和正向代理相反,是服务端的代理,只为目标服务器服务,客户端只知道代理服务器地址,并不知道目标服务器集群的存在。

  • 常用场景:动态内容提供缓存服务、客户端隐藏服务器(集群)的IP地址、Web攻击防护(DoS、DDos)、负载均衡、内容压缩节省网络带宽、Http网络认证;

CDN
  • 含义:Content Delivery Network,内容分发网络

  • 常用场景:1. 将图片等静态资源文件放到CDN上

    ​ 2. 站点加速、点播、直播等场景

  • 解析过程:路由解析 -> 内容分发 -> 负载均衡

    • 无CDN参与时,DNS解析过程(dig www.cc.com +trace命令可查看)

    • 有CDN参与时,DNS解析过程

    • 命令行

      复制代码
      orjrs@localhost ~ % dig www.baidu.com +trace
      ; <<>> DiG 9.10.6 <<>> www.baidu.com +trace
      ;; global options: +cmd
      .			440076	IN	NS	h.root-servers.net.
      .			440076	IN	NS	k.root-servers.net.
      .			440076	IN	NS	b.root-servers.net.
      .			440076	IN	NS	l.root-servers.net.
      .			440076	IN	NS	e.root-servers.net.
      .			440076	IN	NS	a.root-servers.net.
      .			440076	IN	NS	g.root-servers.net.
      .			440076	IN	NS	f.root-servers.net.
      .			440076	IN	NS	j.root-servers.net.
      .			440076	IN	NS	i.root-servers.net.
      .			440076	IN	NS	m.root-servers.net.
      .			440076	IN	NS	d.root-servers.net.
      .			440076	IN	NS	c.root-servers.net.
      ;; Received 228 bytes from 192.168.1.1#53(192.168.1.1) in 12 ms
      
      com.			172800	IN	NS	a.gtld-servers.net.
      com.			172800	IN	NS	b.gtld-servers.net.
      com.			172800	IN	NS	c.gtld-servers.net.
      com.			172800	IN	NS	d.gtld-servers.net.
      com.			172800	IN	NS	e.gtld-servers.net.
      com.			172800	IN	NS	f.gtld-servers.net.
      com.			172800	IN	NS	g.gtld-servers.net.
      com.			172800	IN	NS	h.gtld-servers.net.
      com.			172800	IN	NS	i.gtld-servers.net.
      com.			172800	IN	NS	j.gtld-servers.net.
      com.			172800	IN	NS	k.gtld-servers.net.
      com.			172800	IN	NS	l.gtld-servers.net.
      com.			172800	IN	NS	m.gtld-servers.net.
      com.			86400	IN	DS	30909 8 2 E2D3C916F6DEEAC73294E8268FB5885044A833FC5459588F4A9184CF C41A5766
      com.			86400	IN	RRSIG	DS 8 1 86400 20220522050000 20220509040000 47671 . k2Vb08gFGfFhUWeBxoVSwjD5iJ85jhbu0D8ScFZvxbsRGRNWbOo5I6/F FGNKmH7rxcsOWU5rRoC+G46QuE5JhoB74I73dZEBASYD4diRz9VNgyWN nTs/Oqi/KVXmIoiPTdwF2akaad1Nv3/oQmdx1fdr/0tQAXtCQmm7LK+e tn3IIAD1ibQCyDp0i41NZVlj+xEITjGZV7TiovQwTdQsAenfFhlzvp9J 6tETOjjBzqY4oZDLRl1TZd+kw+RHVNa/IsdzUZkJitUWWD2Abw7S5jMW kenLhMl9RhpRZeivprS8ghtk9Mks7Zx7ZN+r+B14ZOapHB7xRHS2xb6i ADtz7g==
      ;; Received 1173 bytes from 192.58.128.30#53(j.root-servers.net) in 41 ms
      
      baidu.com.		172800	IN	NS	ns2.baidu.com.
      baidu.com.		172800	IN	NS	ns3.baidu.com.
      baidu.com.		172800	IN	NS	ns4.baidu.com.
      baidu.com.		172800	IN	NS	ns1.baidu.com.
      baidu.com.		172800	IN	NS	ns7.baidu.com.
      CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN NSEC3 1 1 0 - CK0Q1GIN43N1ARRC9OSM6QPQR81H5M9A  NS SOA RRSIG DNSKEY NSEC3PARAM
      CK0POJMG874LJREF7EFN8430QVIT8BSM.com. 86400 IN RRSIG NSEC3 8 2 86400 20220515042345 20220508031345 37269 com. G85af9yVUZB2hay2bsvLuxHRzhsPSr2ScZLnDEQq3mZ9EDgIHcvekTAb xQHTJ7Szcan/pzg7SKApdn53zCYbTRZ685WBp3i50CAwjORwnXXf6Uwc kgEPiq7/dhi6X5/0HV3ceNfZ5P9N8xWWJF0O2ekuOvXzMu97+xwa9RON KLsZ9GSk64hm+XJ4HKDQni6gLoPBrV8eMuNCdc7MJmr6MA==
      HPVUVSGH5TFIA7CM6SS6SMPOS87OE0CE.com. 86400 IN NSEC3 1 1 0 - HPVV8SARM2LDLRBTVC5EP1CUB1EF7LOP  NS DS RRSIG
      HPVUVSGH5TFIA7CM6SS6SMPOS87OE0CE.com. 86400 IN RRSIG NSEC3 8 2 86400 20220515054330 20220508043330 37269 com. CXkfM8s4RkGi2pX2HSqLUtMDnxRiAg3NyoU1ZESE62bPCyF8y+U9zf4u GvuQUTmVXe9vXwClTWb6FK3WhtsGyOcBYv3Wi9UB3iG6pOXwMyz2rfyr xFFuwD/BSFgLDQqsnk4a4kiTtr6mBOHP5WiTVKCNHIOgugzy+W1t06na OWBCmK5bZYmy2h9wOv7qkF6efc/GqH17ryrj0+I5U161MA==
      ;; Received 817 bytes from 192.31.80.30#53(d.gtld-servers.net) in 199 ms
      
      www.baidu.com.		1200	IN	CNAME	www.a.shifen.com.
      ;; Received 72 bytes from 112.80.248.64#53(ns3.baidu.com) in 41 ms
      orjrs@localhost ~ % 

服务端缓存

LocalCache

具体参考《本地缓存》

分布式缓存

如redis

操作系统缓存

  • 操作系统内核负责管理磁盘缓存,比较典型的就有主存中的页面缓存技术(PageCache)

缓存淘汰策略

  • noeviction 无淘汰机制
  • volatile-ttl 设置存活时间。当内存不足的时候,在过期时间的键空间中,优先移除过期时间最早的key
  • volatile-random 当内存不足的时候,在过期时间的键空间中,随机淘汰数据。由于无法把冷数据筛选出来,会造成缓存污染
  • volatile-lru 当内存不足的时候,在过期时间的键空间中,溢出最近最少访问的key。但对于只访问一次的数据,无法全部筛选出来
  • volatile-lfu LFU策略在LRU策略基础上进行了优化,筛选数据是优先筛选并淘汰访问次数少的数据
  • allkeys-random 当内存不足的时候,在键空间中,随机淘汰数据。
  • allkeys-lru 当内存不足的时候,在键空间中,溢出最近最少访问的key。
  • allkeys-lfu 当内存不足的时候,在键空间中,优先筛选并淘汰访问次数少的数据。

缓存常见问题

缓存击穿

缓存击穿是一个失效的key被大量请求的集中访问(并量访问),导致请求全部打在数据库上。

原因:

  • 热点数据key突然失效,且大量的请求同时发生

解决方案:

  • 互斥锁或阻塞队列

    Java的Sychronized、lock,mechache的add,Redis的setnx都可以实现,其本质利用tryLock重入锁

  • 热点key不失效

缓存穿透

缓存穿透访问一个key时,其value为null,导致直接穿透缓存去访问DB。

原因

  • 黑客攻击,利用空数据查询,比如用不存在的商品信息、用户信息来查询
  • 缓存污染,利用网络爬虫技术,不断查询或更新冷数据,导致缓存存在大量冷数据,而热数据被驱逐

解决方案:

  • 缓存空值,即把为null值的key也存在缓存里

  • 用布隆过滤器,如Google的BloomFilter

    布隆过滤器优缺点

    优点:1. 查找快,时间复杂度是O(K),其中K是hash函数的个数

    ​ 2. 使用bitMap方式实现,使用数组

缓存雪崩

缓存雪崩时大量key在同一时间失效,同时大量并发访问,cache miss后直接访问数据库,导致数据库负荷而拒绝连接或宕机。

原因:

  • 缓存失效时间集中
  • 缓存宕机

解决方案:

  • 分散缓存失效时间

    Key的TTL加上随机数

  • 使用多级缓存

  • 熔断机制

以下为Redis高可用方案

相关推荐
心勤则明9 分钟前
JVM(Java虚拟机)运行时数据区
java·jvm·chrome
皮皮林55131 分钟前
多账号统一登录(实现方案)
java
越来越无动于衷1 小时前
智慧社区(八)——社区人脸识别出入管理系统设计与实现
java·开发语言·spring boot·python·mysql
Mr Aokey1 小时前
注解退散!纯XML打造MyBatis持久层的终极形态
xml·java·mybatis
向日葵花子(* ̄︶ ̄)1 小时前
Eclipse中导入新项目,右键项目没有Run on Server,Tomcat的add and remove找不到项目
java·eclipse
超级小忍2 小时前
Maven 常用命令详解
java·开发语言·maven
Olrookie2 小时前
若依前后端分离版学习笔记(五)——Spring Boot简介与Spring Security
笔记·后端·学习·spring·ruoyi
小白的代码日记3 小时前
基于 Spring Boot 的小区人脸识别与出入记录管理系统实现
java·spring boot·后端
hty624 小时前
Spring Boot 注解式大文件 Excel 导入工具:excel‑import‑spring‑boot‑starter
java
李少兄4 小时前
解决IntelliJ IDEA 项目名称后带中括号问题(模块名不一致)
java·ide·intellij-idea