缓存是什么
内存又称内部存储器和主存储器(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
操作系统缓存
缓存淘汰策略
- 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。
原因:
解决方案:
-
用布隆过滤器,如Google的BloomFilter
布隆过滤器优缺点
优点:1. 查找快,时间复杂度是O(K),其中K是hash函数的个数
2. 使用bitMap方式实现,使用数组
缓存雪崩
缓存雪崩时大量key在同一时间失效,同时大量并发访问,cache miss后直接访问数据库,导致数据库负荷而拒绝连接或宕机。
原因:
解决方案:
以下为Redis高可用方案