为什么要做多级缓存?
一 搞清楚为什么要用缓存?
总所周知,目前我们常规使用过的mysql等数据库的数据都是存储在物理硬盘,即便是企业级的ssd硬盘,相较于我们计算机的内存来说,都是相差一个数量级的,特别是大量的业务,其实都是属于读多写少的场景,所以我们需要使用一些缓存,辅助我们做读写分离的操作,提升系统的性能,如下图:
二 各级缓存
接下来,我们从一张涉及了多级缓存的图入手,来理解如何去做这样的多级缓存:
从上到下分别是:
- 客户端/应用层
- 业务层
- 数据层
三 客户端/应用层缓存
我们先分析客户端应该怎么做缓存,例如百度首页:
图中两个红色箭头处,可以看到,其图片这个数据是第一次请求后,保存在本地,然后从本地加载的,其存在过期时间,对静态资源进行缓存可以减少大量的文件资源请求。
接着我们来看应用层缓存的设计,应用层缓存设计主要就是CDN内容分发网络,即如果资源在北京,海南的用户如果全部都去北京的服务器获取内容,那么网络资源消耗和延迟是必然存在的,所以我们需要设计一种就近的资源分发系统,如下:
其实这就是缓存,请求通过智能dns进行路由到最近的节点,一种在应用层的缓存。
大厂在CDN方面还提供跟进一步的功能,如下阿里云:
可以为用户提供缓存过期时间,自定义http响应头的功能等,这里有一个值得我们关注的问题,即expire与Cache-control的区别:
Expires是指定具体某个时间点缓存到期,而Cache-Control则代表缓存的有效期是多长时间。Expires设置时间,Cache-Control设置时长。
四 nginx缓存
nginx在代理请求以及流量的过程中,也是可以通过设置缓存来提升性能,如下简单示例:
五 服务层缓存
服务层缓存可以分为进程内缓存和进程外缓存。
- 进程内缓存
进程内缓存即我们常说的分布式缓存,如redis等,进程内缓存的应用非常多,如mybatis的一级缓存等(为什么很多sql查第一次慢,后面就快了),如下图:
很多人在设计缓存的时候,认为只要加一个redis就行了,其实不是,我们在设计缓存的时候,一般要遵守如下:
- 先近后远
- 由快到慢
两个规则来进行逐级访问。
即我们在设计相关的数据时要结合进程内缓存以及分布式缓存,如下图:
进程内我们采用本地缓存,同时设计对应的分布式缓存。
两级缓存设计后,我们必然遇到其他的问题,例如一致性的问题,如下图:
即如何通知其他人,数据库的数据已经被更新了?常用的解决方案即采用异步通知,如下图:
由于以上问题又会产生中间件可靠性的问题,在此先不做解释,但是基于缓存层面我们尽可能做到只对一些读多写少的数据进行缓存,且大多数以下场景的数据可以设计缓存:
- 缓存的数据是稳定的,即一些不会变的邮政编码,省市树,分类,归档数据
- 瞬时可能会产生极高并发的场景,如12306等,即提前预热
- 一定程度上允许数据不一致