目录
1、缓存是什么?为啥要用缓存?
2、常用的缓存工具
3. 手写一个LRU算法
4. 使用缓存有哪些常见隐患?
大家好,我是四九城最豪横的小耳朵。
今天咱们来用大白话聊聊缓存常见的几个面试题。
1、 缓存是什么?为啥要用缓存?
缓存,就是数据交换的缓冲区,目的是,把读写速度慢的介质的数据保存在读写速度快的介质中,从而提高读写速度,减少时间消耗。
对于CPU 高速缓存 ,高速缓存的读写速度远高于内存。CPU 读数据时,如果在高速缓存中找到所需数据,就不需要读内存; CPU 写数据时,先写到高速缓存,再回写到内存。
对于磁盘缓存,其实就把常用的磁盘数据保存在内存中,内存读写速度也是远高于磁盘的。读数据时从内存读取。写数据时,可先写到内存,定时或定量回写到磁盘,或者是同步回写。这样可以提高磁盘IO的吞吐量。
如上我们可以得出结论,使用缓存的目的,就是提升读写性能。而实际业务场景下,更多的是为了提升读性能,带来更好的性能,更高的并发量
2、 常用的缓存工具
日常业务中,我们使用比较多的数据库是 MySQL ,缓存是 Redis 。我们将 MySQL 的热点数据,缓存到 Redis 中,提升读取性能,也减小 MySQL 的读取压力。例如说:
微博的热点事件排行榜,读取的频率特别高,且要实时更新阅读量,使用 Redis 记录排行榜,可以提升性能和并发。
商品信息,数据更新的频率不高,但是读取的频率很高,特别是热门商品。
在 Java 后端开发中,常见的缓存工具和框架列举如下:
本地缓存:Guava LocalCache、Ehcache。Ehcache 的功能更加丰富。
分布式缓存:Redis、Memcached。Redis 最为主流和常用。
3、 手写一个LRU算法
缓存算法,比较常见的是三种:
LRU(least recently used ,最近最少使用)
LFU(Least Frequently used ,最不经常使用)
FIFO(first in first out ,先进先出)
手写 LRU 代码的实现有多种方式。其中最简单的是基于 LinkedHashMap 来实现,原理就是把最近最少访问的数据放到map的尾部,方便删除,那么最近最常访问的就会按顺序排在最前面。其实现代码如下:
class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int CACHE_SIZE;
/**
* 传递进来最多能缓存多少数据
*
* @param cacheSize 缓存大小
*/
public LRUCache(int cacheSize) {
// true 表示让 LinkedHashMap 按照访问顺序来进行排序,最近访问的放在头部,最老访问的放在尾部。
super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);
CACHE_SIZE = cacheSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
// 当 map 中的数据量大于指定的缓存个数的时候,就自动删除最老的数据。
return size() > CACHE_SIZE;
}
}
4、使用缓存有哪些常见隐患?
常见的问题有以下6种:
缓存何时写入?并且写时如何避免并发重复写入?
缓存如何失效?
缓存和 DB 的一致性如何保证?
如何避免缓存穿透的问题?
如何避免缓存击穿的问题?
如果避免缓存雪崩的问题?
End
作者简介:豪横的小耳朵,一个豪横的程序员。想和大家一起在技术的世界里豪横,用技术的眼光去看待世界。欢迎扫描下方二维码,持续关注,一大波原创系列文章正在路上。
扫码关注后回复“666”,可免费获取下图所示的java高级工程师学习资料一份。