一般来说,对于经常被访问的数据,希望可以快速的返回给访问者,采用内存进行缓存就是很好的方式,直接访问内存中已缓存的数据可以被更快的被访问到,分布式中常用的缓存Ehcache,Redis等等;下面介绍几种缓存中常用的缓存淘汰策略:
- FIFO:First In First Out,先进先出:判断存储时间,排队伍尾部(长时间未用)的先被淘汰;
- LFU: Least Frequently Used,最近最少使用,被使用次数最少的缓存先被淘汰;
- LRU:Least Recently Used,最近最少被使用的,就是淘汰长时间未用的数据,一般用过的数据会进行更新到前排,认为是常用的数据;
- LRU缓存机制的实现,采用的是HashMap+DoubleLinkedList,采用Map是其查找数据的O(1)复杂度,而更新删除和插入数据采用双向链表可以快速进行定位操作,使用 key 和 value 作为双向链表的节点,在双向链表的头部添加该节点,并将 key 和该节点添加进哈希表中,我们首先使用哈希表进行定位,找出缓存项在双向链表中的位置,随后将其移动到双向链表的头部,即可在 O(1) 的时间内完成 get 或者 put 操作,具体的方法如下:
- 哈希表即为普通的哈希映射(HashMap),通过缓存数据的键映射到其在双向链表中的位置。
- 双向链表按照被使用的顺序存储了这些键值对,靠近头部的键值对是最近使用的,而靠近尾部的键值对是最久未使用的。
- 对于 get 操作,首先判断 key 是否存在:
1.若 key 不存在,则返回−1;
2.若 key 存在,则 key 对应的节点是最近被使用的节点,通过哈希表定位到该节点在双 向链表中的位置,并将其移动到双向链表的头部,最后返回该节点的值。 - 对于 put 操作,首先判断 key 是否存在:
1.若 key 不存在,使用 key 和 value 创建一个新的节点,在双向链表的头部添加该节点,并将 key 和该节点添加进哈希表中。然后判断双向链表的节点数是否超出容量,如果超出容量,则删除双向链表的尾部节点,并删除哈希表中对应的项;
2.若 key 存在,则与 get 操