1、缓存基本概念

一、缓存为王

1、缓存目的

  • 降低系统的响应时间、减少网络传送时间和应用延时时间,进而提高了系统的吞吐量,增加了系统的并发用户数量。
  • 有效的减少底层关键组件如核心应用、数据库等的压力。在高并发下有效的减轻系统的负荷。

2、使用缓存后存在的问题

  • 使用缓存后存在的问题:在一定程度上会牺牲数据的强一致性,如何保证高可用性和数据强一直性就要根据业务场景做出衡量(CAP理论)

3、缓存的适用场景和不适用场景举例

(1)适用场景
  • 读密集型的应用
  • 存在热点数据的应用
  • 对响应时效要求较高的应用
  • 对一致性要求不是很严格的场景
  • 高并发、高流量下面
(2)不适用场景
  • 读少写多的场景
  • 数据更新频繁的场景
  • 对数据一致性要求非常严格的场景

4、缓存分类

(1)客户端缓存
  • 静态页面缓存
  • 浏览器缓存
  • app应用缓存
(2)网络中间层缓存
  • web代理缓存(正向代理缓存-squid)
  • 边缘缓存(反向代理缓存-nginx、cdn)
(3)服务端缓存
  • 数据库缓存(mysql查询缓存、InnoDB缓存)
  • 平台级缓存(ehcache、guava)
(4)应用级缓存
  • redis、memcached等nosql

5、缓存算法

(1)缓存命中率
  • 缓存命中

缓存命中率是从缓存中读取数据的次数与读取总次数的比率,命中率越高越好。
缓存命中率是一个重要的指标,应用通过监控这个指标来看缓存是否工作良好

(2)缓存回收策略

1.基于空间:当超过设定的存储空间时候,就会触发一定策略移除数据
2.基于容量:缓存设置了最大容量大小,当超过这个容量大小收也会触发回收策略
3.基于时间:
TTL(time to live):存活期,即缓存数据从创建开始直到到期的一个时间段(不管这个时间段数据有欸有被访问,都会过期)
TTI(time to idle):空闲期,即缓存数据多久没被访问后移除缓存的时间。
4.基于java对象:(1)软引用,jvm堆不足的时候,会回收软引用的对象(2)弱引用:垃圾回收时候,如果是弱引用则直接回收

(2)缓存失效策略

1、LRU(least-recent-Used):替换最近被请求最少的对象,最近最少使用算法
2、LFU(least-frequently-used):替换访问次数最少的缓存,最不常用算法
3、LRU2(least-recently-used-2):LRU变种,把被两次访问的对象放入缓存池,缓存池满后就会丢弃两次最少使用的缓存对象去除。
4、FIFO(first-in-first-out):队列替换策略,先进先出算法
5、random cache:随意替换缓存数据

6、使用共有云的缓存服务特点(基于redis存储为例)

  • 动态扩展redis服务的存储空间
  • 数据基本采用一主一备的主备模式
  • 自动容灾,当主发生故障后,自动切换到从服务。实现高可用
  • 成本较低

二、从cpu缓存看分布式缓存架构

1、cpu缓存架构

(1)cpu缓存架构
  • cpu 首先使用自己的寄存器,然后使用L1/L2/L3缓存(先使用速度最快的L1缓存,然后使用L2缓存,然后就是L3缓存)。在cpu中为何会有多级缓存呢?cpu的缓存存在是为了解决内存和cpu两者之间计算速度的差异,引入缓存来提高性能。cpu中每一次缓存的速度差别很大,越快的缓存容量越小,成本也越高。


    计算机缓存应用

    cpu缓存架构
  • 不同缓存的性能不一样,在cpu的密集运算中,越少访问内存则越好,一次访问如果能命中L1、L2缓存的话则认为是比较高效的了,如果命中L3说明就要变成读取一次内存操作,这样大大的较少了并发性能。


    cpu缓存性能差别
(2)cpu缓存执行流程
  • cpu核心访问(读、写)L1如果没有命中,则访问L2和L3,在L3中如果还没有命中就操作一次内存。
  • 多级缓存的存取流程:在L1缓存中通过LRU策略逐出的数据同步到L2,在L2中逐出的数据同步到L3,在L3逐出的数据才同步到内存中。
  • cpu读写数据时候的缓存策略:(1)读操作会先检查缓存,在缓存中没有则会载入数据到缓存中(2)写操作,如果缓存中没有则写入缓存,在执行写操作。这里并不会同步写缓存数据到内存中,而是通过硬件级别的异步操作写回内存(这样大大提升了缓存的效率)
(3)高级知识点:缓存行和伪共享
  • 缓存行:内存是以缓存行为存储单位的,一个缓存行存储字节大小为2的倍数
  • 伪共享:多个线程中同时读写一个缓存行的不同变量时候,尽管这些变量之间没有任何的联系,但是在多个线程中同样要进行同步,从而导致性能低下的情况。在多线程环境下面,需要保证多个线程不同时对一个缓存行或者变量进行读写。(也就是说为了降低对缓存行的抢夺,可以对缓存进行字节补充,使一个变量隔离在一个缓存行中,以较少伪共享带来的性能损耗)

实战之一:jvm中对缓存行的优化
实战之二:无锁队列实际上就是通过解决伪共享的方式提高效率的,通过RingBuffer的游标和BatchEventProcessor的序列变量之后填充变量,并使之与64字节大小的缓存行对齐,来解决伪竞争

(4)从cpu缓存体系看分布式缓存体系
  • 在cpu缓存架构中,cpu通过定义内存类型和一致性解析来解决多核环境下的性能和一致性问题。类比cpu缓存,分布式缓存也能得到类似的情况。


    cpu缓存架构与分布式缓存架构类比
  • 分布式缓存架构要解决的最重要几个问题(缓存高可用、缓存高并发、缓存数据一致性等)

参考:
《深入分布式缓存从实践到原理》
《可伸缩服务架构》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容