系统性能提升--缓存篇,什么是缓存(1)

缓存起源

	Cache 一词来源于1967年的一篇电子工程期刊论文。其作者将法语词“cache”赋予“safekeeping storage”的涵义,用于计算机工程领域。

PC-AT/XT和80286时代,没有 Cache,CPU和内存都很慢,CPU直接访问内存。80386的芯片组增加了对可选的Cache的支持,高级主板带有64KB,甚至高端大气上档次的128KB Write-Through Cache。80486 CPU里面加入了8KB的L1 Unified Cache,当时也叫做内部Cache,不分代码和数据,都存在一起;芯片组中的Cache,变成了L2,也被叫做外部Cache,从128KB到256KB不等;增加了Write-back的Cache属性。Pentium CPU的L1 Cache分为Code和data,各自8KB;L2还被放在主板上。Pentium Pro的L2被放入到CPU的Package上。Pentium 4开始,L2 Cache被放入了CPU的Die中。从Intel Core CPU开始,L2 Cache为多核共享。

如今缓存的概念已被扩充,不仅在CPU和主内存之间有Cache,而且在内存和硬盘之间也有Cache(磁盘缓存),乃至在硬盘与网络之间也有某种意义上的 Cache──称为Internet临时文件夹或网络内容缓存等。凡是位于速度相差较大的两种硬件之间,用于协调两者数据传输速度差异的结构,均可称之为Cache。

缓存之所以有效,主要是因为程序运行时对内存的访问呈现局部性(Locality)特征。这种局部性既包括空间局部性(Spatial Locality),也包括时间局部性(Temporal Locality)。有效利用这种局部性,缓存可以达到极高的命中率。

缓存使用场景

什么时候可以使用缓存

缓存的提出主要是应对的是__读取效率__ 和 吞吐效率 两方面的问题

读取效率

字面上很好理解,举一个case:
用户想访问服务 A 获取一批数据, 数据实际上是存在于 Mysql 中
没有缓存技术,服务A 就需要先去查询 Mysql 拿到数据后再返回给业务(如果 Mysql 此时很忙,那么你的查询耗时会出现激增)
使用缓存技术,服务A 已经先通过预查询 Mysql 把数据缓存起来了,那么在用户需要的时候就可以直接返回给用户,耗时很短,
缓存的使用带来了效率的明显提升(这里提一个问题)
服务A缓存了mysql 数据,那么假设 mysql 数据发生了变动,服务A如何感知,如何解决数据一致性的问题?(下一篇文章会提到)

吞吐效率

读取效率和吞吐效率实质上是一个互补的关系,读取效率的提升,进而会带来吞吐效率的提升,这里再举另外一个类比的case帮助直观理解
pageCache 的使用
为了提升对文件的读写效率,Linux 内核会以页大小(4KB)为单位,将文件划分为多数据块。当用户对文件中的某个数据块进行读写操作时,内核首先会申请一个内存页(称为 PageCache,页缓存)与文件中的数据块进行绑定。
当用户对文件进行读写的实际处理:
从文件中读取数据时,该数据所在的页缓存已经存在,那么就直接把页缓存的数据拷贝给用户即可。否则,内核首先会申请一个空闲的内存页(页缓存),然后从文件中读取数据到页缓存,并且把页缓存的数据拷贝给用户。
写入数据时,数据直接写入到页缓存,然后交由内核定时把这些页缓存刷新到文件中。
读写效率的提升极大程度的提高了系统的整体吞吐效率。

缓存需要考虑的问题

根据个人的理解,缓存的本质是通过空间上的消耗换取时间上的加速,因此,使用缓存也是需要代价的,最典型的就是缓存会占据 on-heap memory(堆内内存) 空间,即使你使用的是 off-heap memory(堆外内存),但是在读取的时候也需要加载到堆内才能被用户态应用用程序直接访问。所以,哪些情况下可以使用缓存技术是很值得思考的问题。
缓存其实主要的收益其实来自于读,因此需要关注一些核心的指标,比如读写比和命中率

读写比

	如果数据大部分时候都是在写入,很少会读取到,那么使用缓存其实没有太大的时间加速效率,使用缓存可能事倍功半。

命中率

缓存很关注命中率指标,如果缓存中的数据命中率很低,那么说明这个服务不适合使用缓存,或者说需要进一步的排查与优化缓存使用方式。

内存使用情况

缓存实际上是使用的on-heap 空间,对内存的消耗会对服务造成的影响是很重要的一环
此外,如下基于上面几个指标的衍生问题也需要关注:

指标
有多少 key,需要多大空间?单条entry 的大小
缓存穿透如何处理
缓存何时更新
缓存和数据源的数据一致性
使用缓存引入什么影响?如对堆内缓存影响 GC,序列化消耗 CPU等
怎么监控,统计命中?

缓存划分

缓存有各类特征,而且有不同介质的区别,那么实际工程中我们怎么去对缓存分类呢?在目前的应用服务框架中,比较常见的,时根据缓存雨应用的藕合度,分为local cache(本地缓存)和remote cache(分布式缓存):

本地缓存:指的是在应用中的缓存组件,其最大的优点是应用和cache是在同一个进程内部,请求缓存非常快速,没有过多的网络开销等,在单应用不需要集群支持或者集群情况下各节点无需互相通知的场景下使用本地缓存较合适;同时,它的缺点也是应为缓存跟应用程序耦合,多个应用程序无法直接的共享缓存,各应用或集群的各节点都需要维护自己的单独缓存,对内存是一种浪费。

分布式缓存:指的是与应用分离的缓存组件或服务,其最大的优点是自身就是一个独立的应用,与本地应用隔离,多个应用可直接的共享缓存。

本地缓存

Ehcache /Caffeine(Guava)/Hollow/布隆过滤器

分布式缓存

Redis

Redis是一个远程内存数据库(非关系型数据库),性能强劲,具有复制特性以及解决问题而生的独一无二的数据模型。它可以存储键值对与5种不同类型的值之间的映射,可以将存储在内存的键值对数据持久化到硬盘,可以使用复制特性来扩展读性能,还可以使用客户端分片来扩展写性能。

Memcache

memcached是应用较广的开源分布式缓存产品之一,它本身其实不提供分布式解决方案。在服务端,memcached集群环境实际就是一个个memcached服务器的堆积,环境搭建较为简单;cache的分布式主要是在客户端实现,通过客户端的路由处理来达到分布式解决方案的目的。客户端做路由的原理非常简单,应用服务器在每次存取某key的value时,通过某种算法把key映射到某台memcached服务器nodeA上,因此这个key所有操作都在nodeA上。

参考文献

缓存.
缓存那些事
Java本地缓存技术选型(Guava Cache、Caffeine、Encache)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值