常用緩存策略
常用的緩存淘汰策略有以下
- 先進先出算法(FIFO)
- Least Frequently Used(LFU)
淘汰一定時期內被訪問次數最少的頁面,以次數作為參考 - Least Recently Used(LRU)
淘汰最長時間未被使用的頁面,以時間作為參考
這些算法在不同層次的緩存上執行時擁有不同的效率和代價,需根據具體場合選擇最合適的一種。
FIFO
FIFO(First in First out),先進先出。在FIFO Cache設計中,核心原則就是:如果一個數據最先進入緩存中,則應該最早淘汰掉。
1、利用一個雙向鏈表保存數據,
2、當來了新的數據之后便添加到鏈表末尾,
3、如果Cache存滿數據,則把鏈表頭部數據刪除,
4、然后把新的數據添加到鏈表末尾。
5、在訪問數據的時候,如果在Cache中存在該數據的話,則返回對應的value值;
6、否則返回-1。如果想提高訪問效率,可以利用hashmap來保存每個key在鏈表中對應的位置。
LFU

1、新加入數據插入到隊列尾部(因為引用計數為1);
2、 隊列中的數據被訪問后,引用計數增加,隊列重新排序;
3、當需要淘汰數據時,將已經排序的列表最后的數據塊刪除。
LRU

1、新數據插入到鏈表頭部;
2、每當緩存命中(即緩存數據被訪問),則將數據移到鏈表頭部;
3、當鏈表滿的時候,將鏈表尾部的數據丟棄。
Two queues(2Q)
2Q算法有兩個緩存隊列,一個是FIFO隊列,一個是LRU隊列。當數據第一次訪問時,2Q算法將數據緩存在FIFO隊列里面,當數據第二次被訪問時,則將數據從FIFO隊列移到LRU隊列里面,兩個隊列各自按照自己的方法淘汰數據。詳細實現如下:

- 新訪問的數據插入到FIFO隊列;
- 如果數據在FIFO隊列中一直沒有被再次訪問,則最終按照FIFO規則淘汰;
- 如果數據在FIFO隊列中被再次訪問,則將數據移到LRU隊列頭部;
- 如果數據在LRU隊列再次被訪問,則將數據移到LRU隊列頭部;
- LRU隊列淘汰末尾的數據。
這種情況適用與以下場景
當存在熱點數據時,LRU的效率很好,但偶發性的、周期性的批量操作會導致LRU命中率急劇下降,緩存污染情況比較嚴重。
周期性的批量操作,會立即淘汰LRU隊列中的大量數據,導致緩存命中率大幅度下降。而APP常規操作中,有大量偶發批量操作,比如:進入頁面后立即返回,就是很典型的一種。
所以LRU算法並不是一個非常好的選擇。