Table of Contents
Redis,Memcached,和Ehcache等缓存框架,主要的特点是什么?分别适用于哪些业务场景
一个实际的例子
缓存是一个范围相当大的概念。我们可以按前后端分,可以按缓存类型特点分。 从我个人角度而言,事实上任何有数据的地方都可以有缓存。在这里我想首先从自己接触并使用的缓存开始讲起。
我目前用到的缓存是在一个服务器项目里的一个例子。简单的原理如下。
service A需要提供数据给另外几个services:B, C,D调用。如下:
而A服务器每次都需要去数据库里请求对应的数据返回给调用者。后来专门为A服务器做了一个Client,这个Client里面定义了一个map,用于存储从A服务器中获得的数据。
因此当其他程序要从A中取数据的时候,就先判断这个map当中有没有需要的数据,若有,就不用向A发请求。
但是这里有一个问题就是假如缓存的数据失效了或者不是最新的了的话该怎么办。这其实是一个消息中间件的典型应用场景。在A服务器与其他调用者之间需要建立一个消息中间件的机制。
在这个mq上需要根据缓存的对象内容建立一个绑定关系。然后在缓存当中需要配置对应的事件监听者,也就是一个Listener。当A当中的数据,即数据库中的数据更新的时候。A需要发出一个缓存更新的message出去,然后调用者的缓存当中的listener收到这个message,发现消息过期,然后就从新从A中取一次数据,并更新缓存。
除此之外,在mq不工作的时候,由于无法确保缓存的正确性,也应该清除掉缓存,这也是在缓存当中配置一个mq断开的事件监听来实现的。后来这一套流程,已经被spring cache框架所替代,替代框架用到了Guava,ehcache3,redis,用户可以自己选配。
这应该算一个最基本的cache,这个cache有一个显而易见的问题就是,当我的对象非常大的时候,他可能会占很大的空间,并且,这个缓存也做不到自己清理这样的功能,但是一些比较常用的缓存框架,是有这些功能的。
一些总结:cache本质上是以空间换时间。所有的cache的结构都是一个map。
什么是缓存穿透? cache penetration
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。
如何避免?
1:对查询结果为空的情况也进行缓存,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击。缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。
2:对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤
3: 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截。
什么是缓存击穿?cache breakdown
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力
解决方案:
- 设置热点数据永远不过期。
- 加互斥锁。todo
什么是缓存雪崩? cache avalanche
当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。
如何避免?
1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
2:做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期
3:不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
4: 设置热点数据永远不过期。
缓存的分类
缓存按使用场景大概可以分为以下几类:
缓存 | 简介 |
页面缓存 | 页面缓存有两层含义: 一个是页面自身对某些元素或全部元素进行缓存;另一层意思 是服务端将静态页面或动态页面的元素进行缓存, 然后给客户端使用 |
浏览器缓存 | 浏览器缓存是通常只要一次会话。浏览器会在硬盘上专门开辟一个空间来存储资源副 本作为缓存。在用户触发”后退"操作或点击一个之前看过的链接的时候,浏览器缓存会 很管用 |
网络中的缓存 | 网络中的缓存位于客户端和服务端之间, 代理或响应客户端的网络请求, 从而对重复的请求返回缓存中的数据资源。 同时, 接受服务端的请求, 更新缓存中的内容 |
Web 代理缓存 | Web代理几乎是伴随着互联网诞生的, 常用的Web代理分为正向代理、 反向代理和透明代理。 Web代理缓存是将Web代理作为缓存的一种技术 |
边缘缓存 | 边缘缓存中典型的商业化服务就是CDN了,例如AWS的CloudFront, 我国的 Network的简称 |
服务端缓存 | 服务端缓存是整个缓存体系中的重头戏, 从网站的架构演进中已经看到了服务端缓存 是系统性能的重中之重了。 数据库是整个系统中的 "慢性子”,有时候数据库调优能够以小搏大, 在不改变架构和代码逻辑的前提下, 缓存参数的调整往往是条捷径。 在系统开发的 过程中, 可以直接在平台侧使用缓存框架, 当缓存框架无法满足系统对性能的要求时, 就 需要在应用层自主开发应用级缓存了, 即使利用可供参考的开源架构, 应用级缓存的开发也是一件有挑战的事情。 |
数据库缓存 | 数据库属千IO密集型的应用, 主要负责数据的管理及存储。 数据库缓存是一类特殊的 缓存, 是数据库自身的缓存机制。 大多数数据库不需要配置就可以快速运行, 但并没有为 特定的需求进行优化。 在数据库调优的时候, 缓存优化是一项很重要的工作。 以MySQL为例,MySQL中使用了查询缓冲机制, 将SELECT语句和查询结果存放在 缓冲区中, 以后对千同样的SELECT语旬, 将直接从缓冲区中读取结果, 以节省查询时间, 提高了SQL查询的效率 |
参考:https://blog.csdn.net/busidihuang/article/details/80676106
问题来了,那么我们经常听到的分布式缓存(Distribute Cache)