来聊聊缓存吧

今天咱们来一起聊聊缓存这个话题吧。

缓存是什么?

术语

缓存算法

前文提到的策略,也可以称之为替代策略, 既缓存算法。常用的缓存算法有:LRU, LFU, FIFO, Random Cache, 2Q, ARC, MRU等等。本文主要来介绍FIFO,LRU和LFU这三种。

其中LRU和LFU在LeetCode上可以找到题目:

FIFO Cache:

在讲LRU和LFU之前我们先来看一下FIFO算法,这是最简单的缓存算法,可以帮助我们对后续内容的理解。

FIFO大家都知道就是First In First Out,先进先出。

get(key):

如cache中存在该key,则返回其对应的value值,否则返回-1

set(key, value):

如cache中存在该key,则update其value值,如不存在则将其插入,若cache已满,则淘汰最早进入cache的key后再插入新key

LRU Cache (Least Recently Used) 最久没被访问算法:

插入数据时,如果数据项在链表中存在,则把该节点移到链表头部,如果不存在,则新建一个节点,放到链表头部(head的后面);若缓存满了,则删除链表最后一个节点(tail前面的)即可。访问的时候,如果数据项在链表中存在,则将其移动到头部,并返回其value;否则返回-1.

get(key):

如果key在HashMap中存在,则将对应的节点放在表头,并返回其value,如果不存在则返回-1.

set(key, value):

如果key存在于HashMap中,则先重置对应的value值,然后获取当前节点,将其删除,并移动到表头。否则,将其插入到表头。

这里有一个小技巧,就是我们可以把addToHead()和deleteNode()两个方法提前写出来。因为这两个方法在很多地方可以被复用。

LFU Cache (Least Frequently Used) 最近最少使用算法:

get(key):

如果cache中存在key,则返回相应的value值,否则返回-1

set(key, value):

如果cache中存在该key,则重置value值,如果不存在则将该key插入到cache中,若cache已满,则淘汰访问最少的数据。

(1)用小顶堆(PriorityQueue)+HashMap

(2)用数组存储数据项, 用hashmap存储每个数据项在数组中的位置, 为每个数据项设置访问频次,如果命中,频次自增,cache满时用新数据替换频次最低的数据项