精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

通俗講解:緩存、緩存算法和緩存框架簡介

開發(fā) 前端 算法
在這篇文章,我們會去討論緩存,緩存算法,緩存框架以及哪個(gè)緩存框架會更好。

[[437580]]

 引言

我們都聽過 cache,當(dāng)你問他們是什么是緩存的時(shí)候,他們會給你一個(gè)完美的答案,可是他們不知道緩存是怎么構(gòu)建的,或者沒有告訴你應(yīng)該采用什么標(biāo)準(zhǔn)去選擇緩存框架。在這篇文章,我們會去討論緩存,緩存算法,緩存框架以及哪個(gè)緩存框架會更好。

面試

“緩存就是存貯數(shù)據(jù)(使用頻繁的數(shù)據(jù))的臨時(shí)地方,因?yàn)槿≡紨?shù)據(jù)的代價(jià)太大了,所以我可以取得快一些。”

這就是 programmer one (programmer one 是一個(gè)面試者)在面試中的回答(一個(gè)月前,他向公司提交了簡歷,想要應(yīng)聘要求在緩存,緩存框架,大規(guī)模數(shù)據(jù)操作有著豐富經(jīng)驗(yàn)的 java 開發(fā)職位)。

programmer one 通過 hash table 實(shí)現(xiàn)了他自己的緩存,但是他知道的只是他的緩存和他那存儲著150條記錄的 hash table,這就是他認(rèn)為的大規(guī)模數(shù)據(jù)(緩存 = hashtable,只需要在 hash table 查找就好了),所以,讓我們來看看面試的過程吧。

面試官:你選擇的緩存方案,是基于什么標(biāo)準(zhǔn)的?

programmer one:呃,(想了5分鐘)嗯,基于,基于,基于數(shù)據(jù)(咳嗽……)

面試官:excese me ! 能不能重復(fù)一下?

programmer one:數(shù)據(jù)?!

面試官:好的。說說幾種緩存算法以及它們的作用

programmer one:(凝視著面試官,臉上露出了很奇怪的表情,沒有人知道原來人類可以做出這種表情 )

面試官:好吧,那我換個(gè)說法,當(dāng)緩存達(dá)到容量時(shí),會怎么做?

programmer one:容量?嗯(思考……hash table 的容量時(shí)沒有限制的,我能任意增加條目,它會自動擴(kuò)充容量的)(這是 programmer one 的想法,但是他沒有說出來)

面試官對 programmer one 表示感謝(面試過程持續(xù)了10分鐘),之后一個(gè)女士走過來說:謝謝你的時(shí)間,我們會給你打電話的,祝你好心情。這是 programmer one 最糟糕的面試(他沒有看到招聘對求職者有豐富的緩存經(jīng)驗(yàn)背景要求,實(shí)際上,他只看到了豐厚的報(bào)酬 )。

說到做到

programmer one 離開之后,他想要知道這個(gè)面試者說的問題和答案,所以他上網(wǎng)去查,programmer one 對緩存一無所知,除了:當(dāng)我需要緩存的時(shí)候,我就會用 hash table。

在他使用了他最愛的搜索引擎搜索之后,他找到了一篇很不錯(cuò)的關(guān)于緩存文章,并且開始去閱讀……

為什么我們需要緩存?

很久很久以前,在還沒有緩存的時(shí)候……用戶經(jīng)常是去請求一個(gè)對象,而這個(gè)對象是從數(shù)據(jù)庫去取,然后,這個(gè)對象變得越來越大,這個(gè)用戶每次的請求時(shí)間也越來越長了,這也把數(shù)據(jù)庫弄得很痛苦,他無時(shí)不刻不在工作。所以,這個(gè)事情就把用戶和數(shù)據(jù)庫弄得很生氣,接著就有可能發(fā)生下面兩件事情:

1.用戶很煩,在抱怨,甚至不去用這個(gè)應(yīng)用了(這是大多數(shù)情況下都會發(fā)生的)

2.數(shù)據(jù)庫為打包回家,離開這個(gè)應(yīng)用,然后,就出現(xiàn)了大麻煩(沒地方去存儲數(shù)據(jù)了)(發(fā)生在極少數(shù)情況下)

上帝派來了緩存

在幾年之后,IBM(60年代)的研究人員引進(jìn)了一個(gè)新概念,它叫“緩存”。

什么是緩存?

正如開篇所講,緩存是“存貯數(shù)據(jù)(使用頻繁的數(shù)據(jù))的臨時(shí)地方,因?yàn)槿≡紨?shù)據(jù)的代價(jià)太大了,所以我可以取得快一些。”

緩存可以認(rèn)為是數(shù)據(jù)的池,這些數(shù)據(jù)是從數(shù)據(jù)庫里的真實(shí)數(shù)據(jù)復(fù)制出來的,并且為了能別取回,被標(biāo)上了標(biāo)簽(鍵 ID)。太棒了

programmer one 已經(jīng)知道這點(diǎn)了,但是他還不知道下面的緩存術(shù)語。

命中:

當(dāng)客戶發(fā)起一個(gè)請求(我們說他想要查看一個(gè)產(chǎn)品信息),我們的應(yīng)用接受這個(gè)請求,并且如果是在第一次檢查緩存的時(shí)候,需要去數(shù)據(jù)庫讀取產(chǎn)品信息。

如果在緩存中,一個(gè)條目通過一個(gè)標(biāo)記被找到了,這個(gè)條目就會被使用、我們就叫它緩存命中。所以,命中率也就不難理解了。

Cache Miss:

但是這里需要注意兩點(diǎn):

1.如果還有緩存的空間,那么,沒有命中的對象會被存儲到緩存中來。

2.如果緩存滿了,而又沒有命中緩存,那么就會按照某一種策略,把緩存中的舊對象踢出,而把新的對象加入緩存池。而這些策略統(tǒng)稱為替代策略(緩存算法),這些策略會決定到底應(yīng)該提出哪些對象。

存儲成本:

當(dāng)沒有命中時(shí),我們會從數(shù)據(jù)庫取出數(shù)據(jù),然后放入緩存。而把這個(gè)數(shù)據(jù)放入緩存所需要的時(shí)間和空間,就是存儲成本。

索引成本:

和存儲成本相仿。

失效:

當(dāng)存在緩存中的數(shù)據(jù)需要更新時(shí),就意味著緩存中的這個(gè)數(shù)據(jù)失效了。

替代策略:

當(dāng)緩存沒有命中時(shí),并且緩存容量已經(jīng)滿了,就需要在緩存中踢出一個(gè)老的條目,加入一條新的條目,而到底應(yīng)該踢出什么條目,就由替代策略決定。

最優(yōu)替代策略:

最優(yōu)的替代策略就是想把緩存中最沒用的條目給踢出去,但是未來是不能夠被預(yù)知的,所以這種策略是不可能實(shí)現(xiàn)的。但是有很多策略,都是朝著這個(gè)目前去努力。

Java 街惡夢:

當(dāng) programmer one 在讀這篇文章的時(shí)候,他睡著了,并且做了個(gè)惡夢(每個(gè)人都有做惡夢的時(shí)候)。

programmer one:nihahha,我要把你弄失效!(瘋狂的狀態(tài))

緩存對象:別別,讓我活著,他們還需要我,我還有孩子。

programmer one:每個(gè)緩存對象在失效之前都會那樣說。你從什么時(shí)候開始有孩子的?不用擔(dān)心,現(xiàn)在就永遠(yuǎn)消失吧!

哈哈哈哈哈……programmer one 恐怖的笑著,但是警笛打破了沉靜,警察把 programmer one 抓了起來,并且控告他殺死了(失效)一個(gè)仍需被使用的緩存對象,他被押到了監(jiān)獄。

programmer one 突然醒了,他被嚇到了,渾身是汗,他開始環(huán)顧四周,發(fā)現(xiàn)這確實(shí)是個(gè)夢,然后趕緊繼續(xù)閱讀這篇文章,努力的消除自己的恐慌。

在programmer one 醒來之后,他又開始閱讀文章了。

緩存算法

沒有人能說清哪種緩存算法優(yōu)于其他的緩存算法

Least Frequently Used(LFU):

大家好,我是 LFU,我會計(jì)算為每個(gè)緩存對象計(jì)算他們被使用的頻率。我會把最不常用的緩存對象踢走。

Least Recently User(LRU):

我是 LRU 緩存算法,我把最近最少使用的緩存對象給踢走。

我總是需要去了解在什么時(shí)候,用了哪個(gè)緩存對象。如果有人想要了解我為什么總能把最近最少使用的對象踢掉,是非常困難的。

瀏覽器就是使用了我(LRU)作為緩存算法。新的對象會被放在緩存的頂部,當(dāng)緩存達(dá)到了容量極限,我會把底部的對象踢走,而技巧就是:我會把最新被訪問的緩存對象,放到緩存池的頂部。

所以,經(jīng)常被讀取的緩存對象就會一直呆在緩存池中。有兩種方法可以實(shí)現(xiàn)我,array 或者是 linked list。

我的速度很快,我也可以被數(shù)據(jù)訪問模式適配。我有一個(gè)大家庭,他們都可以完善我,甚至做的比我更好(我確實(shí)有時(shí)會嫉妒,但是沒關(guān)系)。我家庭的一些成員包括 LRU2 和 2Q,他們就是為了完善 LRU 而存在的。

Least Recently Used 2(LRU2):

我是 Least Recently Used 2,有人叫我最近最少使用 twice,我更喜歡這個(gè)叫法。我會把被兩次訪問過的對象放入緩存池,當(dāng)緩存池滿了之后,我會把有兩次最少使用的緩存對象踢走。因?yàn)樾枰檶ο?次,訪問負(fù)載就會隨著緩存池的增加而增加。如果把我用在大容量的緩存池中,就會有問題。另外,我還需要跟蹤那么不在緩存的對象,因?yàn)樗麄冞€沒有被第二次讀取。我比LRU好,而且是 adoptive to access 模式 。

Two Queues(2Q):

我是 Two Queues;我把被訪問的數(shù)據(jù)放到 LRU 的緩存中,如果這個(gè)對象再一次被訪問,我就把他轉(zhuǎn)移到第二個(gè)、更大的 LRU 緩存。

我踢走緩存對象是為了保持第一個(gè)緩存池是第二個(gè)緩存池的1/3。當(dāng)緩存的訪問負(fù)載是固定的時(shí)候,把 LRU 換成 LRU2,就比增加緩存的容量更好。這種機(jī)制使得我比 LRU2 更好,我也是 LRU 家族中的一員,而且是 adoptive to access 模式 。

Adaptive Replacement Cache(ARC):

我是 ARC,有人說我是介于 LRU 和 LFU 之間,為了提高效果,我是由2個(gè) LRU 組成,第一個(gè),也就是 L1,包含的條目是最近只被使用過一次的,而第二個(gè) LRU,也就是 L2,包含的是最近被使用過兩次的條目。因此, L1 放的是新的對象,而 L2 放的是常用的對象。所以,別人才會認(rèn)為我是介于 LRU 和 LFU 之間的,不過沒關(guān)系,我不介意。

我被認(rèn)為是性能最好的緩存算法之一,能夠自調(diào),并且是低負(fù)載的。我也保存著歷史對象,這樣,我就可以記住那些被移除的對象,同時(shí),也讓我可以看到被移除的對象是否可以留下,取而代之的是踢走別的對象。我的記憶力很差,但是我很快,適用性也強(qiáng)。

Most Recently Used(MRU):

我是 MRU,和 LRU 是對應(yīng)的。我會移除最近最多被使用的對象,你一定會問我為什么。好吧,讓我告訴你,當(dāng)一次訪問過來的時(shí)候,有些事情是無法預(yù)測的,并且在緩存系統(tǒng)中找出最少最近使用的對象是一項(xiàng)時(shí)間復(fù)雜度非常高的運(yùn)算,這就是為什么我是最好的選擇。

我是數(shù)據(jù)庫內(nèi)存緩存中是多么的常見!每當(dāng)一次緩存記錄的使用,我會把它放到棧的頂端。當(dāng)棧滿了的時(shí)候,你猜怎么著?我會把棧頂?shù)膶ο蠼o換成新進(jìn)來的對象!

First in First out(FIFO):

我是先進(jìn)先出,我是一個(gè)低負(fù)載的算法,并且對緩存對象的管理要求不高。我通過一個(gè)隊(duì)列去跟蹤所有的緩存對象,最近最常用的緩存對象放在后面,而更早的緩存對象放在前面,當(dāng)緩存容量滿時(shí),排在前面的緩存對象會被踢走,然后把新的緩存對象加進(jìn)去。我很快,但是我并不適用。

Second Chance:

大家好,我是 second chance,我是通過 FIFO 修改而來的,被大家叫做 second chance 緩存算法,我比 FIFO 好的地方是我改善了 FIFO 的成本。我是 FIFO 一樣也是在觀察隊(duì)列的前端,但是很FIFO的立刻踢出不同,我會檢查即將要被踢出的對象有沒有之前被使用過的標(biāo)志(1一個(gè) bit 表示),沒有沒有被使用過,我就把他踢出;否則,我會把這個(gè)標(biāo)志位清除,然后把這個(gè)緩存對象當(dāng)做新增緩存對象加入隊(duì)列。你可以想象就這就像一個(gè)環(huán)隊(duì)列。當(dāng)我再一次在隊(duì)頭碰到這個(gè)對象時(shí),由于他已經(jīng)沒有這個(gè)標(biāo)志位了,所以我立刻就把他踢開了。我在速度上比 FIFO 快。

CLock:

我是 Clock,一個(gè)更好的 FIFO,也比 second chance 更好。因?yàn)槲也粫?second chance 那樣把有標(biāo)志的緩存對象放到隊(duì)列的尾部,但是也可以達(dá)到 second chance 的效果。

我持有一個(gè)裝有緩存對象的環(huán)形列表,頭指針指向列表中最老的緩存對象。當(dāng)緩存 miss 發(fā)生并且沒有新的緩存空間時(shí),我會問問指針指向的緩存對象的標(biāo)志位去決定我應(yīng)該怎么做。如果標(biāo)志是0,我會直接用新的緩存對象替代這個(gè)緩存對象;如果標(biāo)志位是1,我會把頭指針遞增,然后重復(fù)這個(gè)過程,知道新的緩存對象能夠被放入。我比 second chance 更快。

Simple time-based:

我是 simple time-based 緩存算法,我通過絕對的時(shí)間周期去失效那些緩存對象。對于新增的對象,我會保存特定的時(shí)間。我很快,但是我并不適用。

Extended time-based expiration:

我是 extended time-based expiration 緩存算法,我是通過相對時(shí)間去失效緩存對象的;對于新增的緩存對象,我會保存特定的時(shí)間,比如是每5分鐘,每天的12點(diǎn)。

Sliding time-based expiration:

我是 sliding time-based expiration,與前面不同的是,被我管理的緩存對象的生命起點(diǎn)是在這個(gè)緩存的最后被訪問時(shí)間算起的。我很快,但是我也不太適用。

其他的緩存算法還考慮到了下面幾點(diǎn):

成本:如果緩存對象有不同的成本,應(yīng)該把那些難以獲得的對象保存下來。

容量:如果緩存對象有不同的大小,應(yīng)該把那些大的緩存對象清除,這樣就可以讓更多的小緩存對象進(jìn)來了。

時(shí)間:一些緩存還保存著緩存的過期時(shí)間。電腦會失效他們,因?yàn)樗麄円呀?jīng)過期了。

根據(jù)緩存對象的大小而不管其他的緩存算法可能是有必要的。

電子郵件!

在讀完這篇文章之后,programmer one 想了一會兒,然后決定給作者發(fā)封郵件,他感覺作者的名字在哪聽過,但是已經(jīng)想不起來了。不管怎樣,他還是把郵件發(fā)送出來了,他詢問了作者在分布式環(huán)境中,緩存是怎么樣工作的。

文章的作者收到了郵件,具有諷刺意味的是,這個(gè)作者就是面試 programmer one 的人 ,作者回復(fù)了……

在這一部分中,我們來看看如何實(shí)現(xiàn)這些著名的緩存算法。以下的代碼只是示例用的,如果你想自己實(shí)現(xiàn)緩存算法,可能自己還得加上一些額外的工作。

LeftOver 機(jī)制

在 programmer one 閱讀了文章之后,他接著看了文章的評論,其中有一篇評論提到了 leftover 機(jī)制——random cache。

Random Cache

我是隨機(jī)緩存,我隨意的替換緩存實(shí)體,沒人敢抱怨。你可以說那個(gè)被替換的實(shí)體很倒霉。通過這些行為,我隨意的去處緩存實(shí)體。我比 FIFO 機(jī)制好,在某些情況下,我甚至比 LRU 好,但是,通常LRU都會比我好。

現(xiàn)在是評論時(shí)間

當(dāng) programmer one 繼續(xù)閱讀評論的時(shí)候,他發(fā)現(xiàn)有個(gè)評論非常有趣,這個(gè)評論實(shí)現(xiàn)了一些緩存算法,應(yīng)該說這個(gè)評論做了一個(gè)鏈向評論者網(wǎng)站的鏈接,programmer one順著鏈接到了那個(gè)網(wǎng)站,接著閱讀。

看看緩存元素(緩存實(shí)體)

  1. publicclassCacheElement 
  2.  
  3.  
  4. privateObjectobjectValue; 
  5.  
  6. privateObjectobjectKey; 
  7.  
  8. privateintindex; 
  9.  
  10. privateinthitCount;// getters and setters 
  11.  
  12.  
  13. //這個(gè)緩存實(shí)體擁有緩存的key和value,這個(gè)實(shí)體的數(shù)據(jù)結(jié)構(gòu)會被以下所有緩存算法用到。 
  14.  
  15. //緩存算法的公用代碼 
  16.  
  17. publicfinalsynchronizedvoidaddElement(Objectkey,Objectvalue) 
  18.  
  19.  
  20. intindex; 
  21.  
  22. Objectobj; 
  23.  
  24. // get the entry from the table 
  25.  
  26. obj = table.get(key); 
  27.  
  28. // If we have the entry already in our table 
  29.  
  30. // then get it and replace only its value. 
  31.  
  32. obj = table.get(key); 
  33.  
  34. if(obj != null
  35.  
  36.  
  37. CacheElement element; 
  38.  
  39. element = (CacheElement)obj; 
  40.  
  41. element.setObjectValue(value); 
  42.  
  43. element.setObjectKey(key); 
  44.  
  45. return
  46.  
  47.  
  48. } 

上面的代碼會被所有的緩存算法實(shí)現(xiàn)用到。這段代碼是用來檢查緩存元素是否在緩存中了,如果是,我們就替換它,但是如果我們找不到這個(gè) key 對應(yīng)的緩存,我們會怎么做呢?那我們就來深入的看看會發(fā)生什么吧!

現(xiàn)場訪問

今天的專題很特殊,因?yàn)槲覀冇刑厥獾目腿耍聦?shí)上他們是我們想要聽的與會者,但是首先,先介紹一下我們的客人:Random Cache,F(xiàn)IFO Cache。讓我們從 Random Cache開始。

看看隨機(jī)緩存的實(shí)現(xiàn)

  1. publicfinalsynchronizedvoidaddElement(Objectkey,Objectvalue) 
  2.  
  3.  
  4. intindex; 
  5.  
  6. Objectobj; 
  7.  
  8. obj = table.get(key); 
  9.  
  10. if(obj != null
  11.  
  12.  
  13. CacheElement element;// Just replace the value. 
  14.  
  15. element = (CacheElement)obj; 
  16.  
  17. element.setObjectValue(value); 
  18.  
  19. element.setObjectKey(key); 
  20.  
  21. return
  22.  
  23. }// If we haven't filled the cache yet, put it at the end. 
  24.  
  25. if(!isFull()) 
  26.  
  27.  
  28. index = numEntries; 
  29.  
  30. ++numEntries; 
  31.  
  32.  
  33. else{// Otherwise, replace a random entry. 
  34.  
  35. index = (int)(cache.length * random.nextFloat()); 
  36.  
  37. table.remove(cache[index].getObjectKey()); 
  38.  
  39.  
  40. cache[index].setObjectValue(value); 
  41.  
  42. cache[index].setObjectKey(key); 
  43.  
  44. table.put(key,cache[index]); 
  45.  
  46.  
  47. //看看FIFO緩算法的實(shí)現(xiàn) 
  48.  
  49. publicfinalsynchronizedvoidaddElement(Objectkey,Objectvalue) 
  50.  
  51.  
  52. intindex; 
  53.  
  54. Objectobj; 
  55.  
  56. obj = table.get(key); 
  57.  
  58. if(obj != null
  59.  
  60.  
  61. CacheElement element;// Just replace the value. 
  62.  
  63. element = (CacheElement)obj; 
  64.  
  65. element.setObjectValue(value); 
  66.  
  67. element.setObjectKey(key); 
  68.  
  69. return
  70.  
  71.  
  72. // If we haven't filled the cache yet, put it at the end. 
  73.  
  74. if(!isFull()) 
  75.  
  76.  
  77. index = numEntries; 
  78.  
  79. ++numEntries; 
  80.  
  81.  
  82. else{// Otherwise, replace the current pointer, 
  83.  
  84. // entry with the new one. 
  85.  
  86. index = current; 
  87.  
  88. // in order to make Circular FIFO 
  89.  
  90. if(++current >= cache.length) 
  91.  
  92. current = 0
  93.  
  94. table.remove(cache[index].getObjectKey()); 
  95.  
  96.  
  97. cache[index].setObjectValue(value); 
  98.  
  99. cache[index].setObjectKey(key); 
  100.  
  101. table.put(key,cache[index]); 
  102.  

看看LFU緩存算法的實(shí)現(xiàn)

  1. publicsynchronizedObjectgetElement(Objectkey) 
  2.  
  3.  
  4. Objectobj; 
  5.  
  6. obj = table.get(key); 
  7.  
  8. if(obj != null
  9.  
  10.  
  11. CacheElement element = (CacheElement)obj; 
  12.  
  13. element.setHitCount(element.getHitCount() + 1); 
  14.  
  15. returnelement.getObjectValue(); 
  16.  
  17.  
  18. returnnull; 
  19.  
  20.  
  21. publicfinalsynchronizedvoidaddElement(Objectkey,Objectvalue) 
  22.  
  23.  
  24. Objectobj; 
  25.  
  26. obj = table.get(key); 
  27.  
  28. if(obj != null
  29.  
  30.  
  31. CacheElement element;// Just replace the value. 
  32.  
  33. element = (CacheElement)obj; 
  34.  
  35. element.setObjectValue(value); 
  36.  
  37. element.setObjectKey(key); 
  38.  
  39. return
  40.  
  41.  
  42. if(!isFull()) 
  43.  
  44.  
  45. index = numEntries; 
  46.  
  47. ++numEntries; 
  48.  
  49.  
  50. else 
  51.  
  52.  
  53. CacheElement element = removeLfuElement(); 
  54.  
  55. index = element.getIndex(); 
  56.  
  57. table.remove(element.getObjectKey()); 
  58.  
  59.  
  60. cache[index].setObjectValue(value); 
  61.  
  62. cache[index].setObjectKey(key); 
  63.  
  64. cache[index].setIndex(index); 
  65.  
  66. table.put(key,cache[index]); 
  67.  
  68.  
  69. publicCacheElement removeLfuElement() 
  70.  
  71.  
  72. CacheElement[]elements = getElementsFromTable(); 
  73.  
  74. CacheElement leastElement = leastHit(elements); 
  75.  
  76. returnleastElement; 
  77.  
  78.  
  79. publicstaticCacheElement leastHit(CacheElement[]elements) 
  80.  
  81.  
  82. CacheElement lowestElement = null
  83.  
  84. for(inti = 0;i < elements.length;i++) 
  85.  
  86.  
  87. CacheElement element = elements[i]; 
  88.  
  89. if(lowestElement == null
  90.  
  91.  
  92. lowestElement = element; 
  93.  
  94.  
  95. else
  96.  
  97. if(element.getHitCount() < lowestElement.getHitCount()) 
  98.  
  99.  
  100. lowestElement = element; 
  101.  
  102.  
  103.  
  104.  
  105. returnlowestElement; 
  106.  

今天的專題很特殊,因?yàn)槲覀冇刑厥獾目腿耍聦?shí)上他們是我們想要聽的與會者,但是首先,先介紹一下我們的客人:Random Cache, FIFO Cache。讓我們從 Random Cache開始。

最重點(diǎn)的代碼,就應(yīng)該是 leastHit 這個(gè)方法,這段代碼就是把

hitCount 最低的元素找出來,然后刪除,給新進(jìn)的緩存元素留位置。

看看LRU緩存算法實(shí)現(xiàn)

  1. privatevoidmoveToFront(intindex) 
  2.  
  3.  
  4. intnextIndex,prevIndex; 
  5.  
  6. if(head != index) 
  7.  
  8.  
  9. nextIndex = next[index]; 
  10.  
  11. prevIndex = prev[index]; 
  12.  
  13. // Only the head has a prev entry that is an invalid index 
  14.  
  15. // so we don't check. 
  16.  
  17. next[prevIndex] = nextIndex; 
  18.  
  19. // Make sure index is valid. If it isn't, we're at the tail 
  20.  
  21. // and don't set prev[next]. 
  22.  
  23. if(nextIndex >= 0
  24.  
  25. prev[nextIndex] = prevIndex; 
  26.  
  27. else 
  28.  
  29. tail = prevIndex; 
  30.  
  31. prev[index] = -1
  32.  
  33. next[index] = head; 
  34.  
  35. prev[head] = index; 
  36.  
  37. head = index; 
  38.  
  39.  
  40.  
  41. publicfinalsynchronizedvoidaddElement(Objectkey,Objectvalue) 
  42.  
  43.  
  44. intindex;Objectobj; 
  45.  
  46. obj = table.get(key); 
  47.  
  48. if(obj != null
  49.  
  50.  
  51. CacheElement entry; 
  52.  
  53. // Just replace the value, but move it to the front. 
  54.  
  55. entry = (CacheElement)obj; 
  56.  
  57. entry.setObjectValue(value); 
  58.  
  59. entry.setObjectKey(key); 
  60.  
  61. moveToFront(entry.getIndex()); 
  62.  
  63. return
  64.  
  65.  
  66. // If we haven't filled the cache yet, place in next available 
  67.  
  68. // spot and move to front. 
  69.  
  70. if(!isFull()) 
  71.  
  72.  
  73. if(_numEntries > 0
  74.  
  75.  
  76. prev[_numEntries] = tail; 
  77.  
  78. next[_numEntries] = -1
  79.  
  80. moveToFront(numEntries); 
  81.  
  82.  
  83. ++numEntries; 
  84.  
  85.  
  86. else{// We replace the tail of the list. 
  87.  
  88. table.remove(cache[tail].getObjectKey()); 
  89.  
  90. moveToFront(tail); 
  91.  
  92.  
  93. cache[head].setObjectValue(value); 
  94.  
  95. cache[head].setObjectKey(key); 
  96.  
  97. table.put(key,cache[head]); 
  98.  

這段代碼的邏輯如 LRU算法 的描述一樣,把再次用到的緩存提取到最前面,而每次刪除的都是最后面的元素。

結(jié)論

我們已經(jīng)看到 LFU緩存算法 和 LRU緩存算法的實(shí)現(xiàn)方式,至于如何實(shí)現(xiàn),采用數(shù)組還是 LinkedHashMap,都由你決定,不夠我一般是小的緩存容量用數(shù)組,大的用 LinkedHashMap。

 

責(zé)任編輯:張燕妮 來源: CPP開發(fā)前沿
相關(guān)推薦

2012-12-17 14:54:55

算法緩存Java

2019-11-05 14:24:31

緩存雪崩框架

2021-08-05 16:10:03

進(jìn)程緩存緩存服務(wù)Java

2017-07-13 16:40:16

偽共享緩存行存儲

2021-12-25 22:28:27

緩存穿透緩存擊穿緩存雪崩

2025-03-03 07:00:00

2010-10-13 16:44:10

MySQL查詢緩存機(jī)制

2009-06-30 14:08:00

Hibernate緩存

2013-07-29 16:22:21

Android緩存框架

2019-10-12 14:19:05

Redis數(shù)據(jù)庫緩存

2023-03-10 13:33:00

緩存穿透緩存擊穿緩存雪崩

2022-05-10 08:58:56

CacheHTTP

2009-11-23 17:56:44

PHP緩存機(jī)制

2010-04-16 13:52:03

Oracle緩存表

2011-08-05 15:51:44

MySQL數(shù)據(jù)庫緩存

2009-09-21 13:49:14

Hiberate3 S

2017-12-27 12:01:39

2021-06-05 09:01:01

Redis緩存雪崩緩存穿透

2022-03-08 00:07:51

緩存雪崩數(shù)據(jù)庫

2022-05-27 07:57:20

緩存穿透緩存雪崩緩存擊穿
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

欧美日韩国产一区精品一区| 性欧美hd调教| 成人av网站免费| 情事1991在线| 欧美性猛交xxxx乱大交少妇| 日韩久久一区| 亚洲动漫第一页| 色一情一乱一伦一区二区三欧美| 国产精品无码白浆高潮| 欧美黄色一级视频| 亚洲美腿欧美激情另类| 天天久久综合网| 麻豆mv在线观看| 日韩美女视频一区| 久久久综合香蕉尹人综合网| 亚洲网站在线免费观看| 亚洲成人在线| 日韩有码视频在线| 自拍视频一区二区| 国产一区二区三区黄网站| 欧美日韩国产丝袜另类| 久久久久久久久影视| 欧美孕妇性xxxⅹ精品hd| 久久91精品国产91久久小草| 51视频国产精品一区二区| 黄色录像二级片| 国内精品久久久久久久影视简单 | 成人avav在线| 国产美女精品视频免费观看| 日韩av电影网址| 香蕉综合视频| 一区二区欧美日韩视频| 女人被狂躁c到高潮| 日韩中文字幕| 91麻豆精品国产综合久久久久久| 无码人妻丰满熟妇区毛片| 国产网红女主播精品视频| 亚洲欧洲成人av每日更新| 视频一区二区三| 可以在线观看的av| 99久久婷婷国产| 国产乱码精品一区二区三区中文 | 亚洲欧洲自拍| 午夜国产不卡在线观看视频| 欧美 日韩 国产精品| 韩国av网站在线| 国产精品国产精品国产专区不蜜 | 国产啪精品视频| 波多野结衣不卡| 丝袜美腿高跟呻吟高潮一区| 欧美亚洲国产成人精品| 99久在线精品99re8热| 禁久久精品乱码| 欧美精品激情在线观看| 久久久久久久国产精品毛片| 欧美区日韩区| www.xxxx欧美| 久久国产精品国语对白| 亚洲一区色图| 欧美激情亚洲国产| 国产大片中文字幕| 一区二区日韩免费看| 91精品国产免费久久久久久| av大片免费在线观看| 国产精品久久久久久模特| 欧美亚洲成人网| 成年人晚上看的视频| 蜜桃视频一区二区| 成人亚洲综合色就1024| 国产免费一区二区三区免费视频| 黄页视频在线91| αv一区二区三区| 色哟哟中文字幕| 2020日本不卡一区二区视频| 日本中文不卡| 免费在线观看黄| 亚洲精品亚洲人成人网在线播放| 大胆欧美熟妇xx| 多野结衣av一区| 色成人在线视频| 我看黄色一级片| 久久中文字幕一区二区| 亚洲第一区中文99精品| 男女做爰猛烈刺激| 亚洲精品tv久久久久久久久久| 久热精品视频在线免费观看| 久久午夜无码鲁丝片| 免费看黄裸体一级大秀欧美| 国产精品一区二区女厕厕| 国产乱人乱偷精品视频a人人澡| 国产精品18久久久久久久久| 免费h精品视频在线播放| 97在线观看免费观看高清 | 久久久久亚洲av无码专区喷水| 日韩影视在线| 色婷婷亚洲综合| 美女被艹视频网站| 亚洲资源网站| 伦理中文字幕亚洲| 日韩欧美在线观看免费| 国产一区二区三区av电影| 精品在线观看一区二区| 欧美13一16娇小xxxx| 亚洲成人免费在线| 91精品999| 亚洲资源网你懂的| 欧美夫妻性生活视频| 蜜臀精品一区二区三区| 国产成人av电影在线| 日韩免费电影一区二区| 欧美hdxxxxx| 欧美日韩中字一区| 人妻少妇精品视频一区二区三区| 欧美国产美女| 国产成人一区二| 人成网站在线观看| 亚洲欧美在线aaa| 无人在线观看的免费高清视频| 天堂va欧美ⅴa亚洲va一国产| 精品在线小视频| 青青草偷拍视频| 美女性感视频久久| 免费h精品视频在线播放| 欧美aaaxxxx做受视频| 欧美日韩黄视频| 国产人妻人伦精品1国产丝袜| 久久久久久久久国产一区| 日本中文字幕成人| 天堂av一区二区三区| 伊人性伊人情综合网| 亚洲第一天堂久久| 成人一区而且| 国产97在线|日韩| 亚洲av激情无码专区在线播放| 一区二区三区四区在线播放| 中文字幕视频三区| 色呦哟—国产精品| 国产精品av在线| 黄色小视频在线观看| 精品日韩中文字幕| 黄色录像a级片| 亚洲伦伦在线| 国产成人一区二区三区免费看| 性xxxfreexxxx性欧美| 欧美人伦禁忌dvd放荡欲情| 一级特黄曰皮片视频| 免费中文字幕日韩欧美| 久久av一区二区三区亚洲| 丰乳肥臀在线| 亚洲第一色中文字幕| 亚洲国产成人精品激情在线| jizz一区二区| 国产二级片在线观看| 台湾亚洲精品一区二区tv| 97在线看免费观看视频在线观看| 日韩性xxxx| 欧美日韩精品在线| 爱爱的免费视频| 久久一日本道色综合久久| 日本在线观看一区| 黄色精品视频网站| 久久福利视频网| 亚洲av无码一区二区三区性色| 亚洲永久精品国产| 97精品人妻一区二区三区蜜桃| 亚洲日本久久| 女同一区二区| 九九热这里有精品| 久久国产精品久久久久| 老司机午夜福利视频| 欧美日韩国产色| 9.1片黄在线观看| 国产一区二区三区国产| 97视频久久久| 精品免费在线| 亚洲最大av在线| 男人av在线播放| 这里精品视频免费| 精品久久久久中文慕人妻| 调教+趴+乳夹+国产+精品| 日韩乱码人妻无码中文字幕久久| 蜜乳av一区二区| 欧美日韩dvd| 亚洲精品亚洲人成在线观看| 国产精品中文字幕在线| 欧美人与牲禽动交com| 日韩精品福利网站| 一区二区三区免费在线| 性久久久久久久久久久久| 亚洲国产天堂av| 国产成人综合在线观看| av免费中文字幕| 亚洲乱码在线| 欧美一区二区三区成人久久片| 99国内精品久久久久| 欧美成人激情视频| 韩国中文字幕2020精品| 日韩三级在线观看| 久久人人爽人人爽人人片av免费| 亚洲免费在线看| 成人性生交大免费看| 国产精一品亚洲二区在线视频| 亚洲国产精品久久久久婷蜜芽| 91亚洲成人| 麻豆精品蜜桃一区二区三区| 精品视频一区二区三区| 日韩av成人在线观看| 欧美xxxbbb| 搡老女人一区二区三区视频tv| 手机在线观看毛片| 911精品国产一区二区在线| 性色av免费观看| 亚洲一二三四久久| 欧美 日韩 国产 一区二区三区| 久久久夜色精品亚洲| youjizz.com日本| 韩国v欧美v日本v亚洲v| 日韩欧美黄色大片| 99成人精品| 97碰在线视频| 亚洲成人三区| 亚洲一区三区| 欧美日韩国产在线观看网站| 精品一区二区国产| 在线日韩成人| 亚洲最大成人网色| 婷婷激情成人| 国产精品中文字幕在线| 国产成人精品一区二三区在线观看 | 欧美色图在线视频| 国产第100页| 亚洲综合精品自拍| 欧美日韩偷拍视频| 亚洲卡通欧美制服中文| 人人干在线观看| 国产精品久久久久久一区二区三区| 免费看黄色aaaaaa 片| 97成人超碰视| 国产精品一级黄片| 不卡高清视频专区| 尤物网站在线观看| 成人免费黄色大片| 日本一区二区免费视频| 成人综合婷婷国产精品久久蜜臀| 国产黄色一区二区三区| 国产剧情av麻豆香蕉精品| 三大队在线观看| 国产成人午夜精品5599| 无码人妻丰满熟妇区毛片蜜桃精品 | 色鬼7777久久| 国产视频久久久久| 精品999视频| 在线观看久久av| 网友自拍视频在线| 久久精品久久久久久| а√天堂在线官网| 欧美极品美女电影一区| 高清电影在线观看免费| 97成人精品区在线播放| 亚洲最大网站| 国产精品欧美风情| 亚洲久草在线| 福利视频一区二区三区| 久久中文字幕导航| 欧美一区二视频在线免费观看| 激情综合网五月| 亚洲欧洲一区二区| 欧美国产三级| 春日野结衣av| 免费的成人av| 97人人模人人爽人人澡| 成人av手机在线观看| 香蕉视频久久久| 亚洲视频在线观看一区| 中文字幕一区二区三区手机版 | 亚洲性在线观看| 日韩三级中文字幕| 日本亚洲一区| 日韩视频在线一区| 久草在线视频资源| 日韩免费视频在线观看| 国产午夜久久av| 国产精品一区二区免费| 精品国产欧美日韩| www.18av.com| 日韩激情在线观看| 又色又爽又黄18网站| 久久综合色播五月| 亚洲色偷偷综合亚洲av伊人| 亚洲成人资源在线| 中文字幕a级片| 精品国产乱码久久久久久图片| 久热av在线| 欧美精品一二区| 日韩影片中文字幕| 97人摸人人澡人人人超一碰| 亚洲福利天堂| 国产情侣第一页| 奇米色一区二区三区四区| 师生出轨h灌满了1v1| 国产欧美日韩综合| 国产精品变态另类虐交| 欧美熟乱第一页| 亚州视频一区二区三区| 久久久国产精品x99av| 欧美一级大片| 国产精品久久久久久久小唯西川 | av一区二区久久| 成人无码精品1区2区3区免费看 | 国产亚洲视频系列| 久久免费视频6| 在线播放/欧美激情| 久久久久国产精品嫩草影院| 欧美精品在线观看91| 97久久网站| 久久久久久久久一区二区| 欧美国产三区| www.欧美激情.com| 中文字幕第一页久久| 日韩欧美成人一区二区三区| 欧美videossexotv100| 免费黄色网页在线观看| 国产精国产精品| 色橹橹欧美在线观看视频高清| 日韩精品一区二区三区四| 乱一区二区av| av网站免费在线看| 大桥未久av一区二区三区| 亚洲欧美激情国产综合久久久| 久久精品国产2020观看福利| 成人mm视频在线观看| 欧美日韩高清在线一区| 中日韩男男gay无套| 黄色免费视频网站| 亚洲一区二区三区精品在线| 国产麻豆免费视频| 久久久精品久久久| 日韩伦理一区二区| 伊人婷婷久久| 精品在线一区二区三区| 日本成人免费在线观看 | 久久93精品国产91久久综合| 日韩欧美国产综合在线| 成人免费视频国产在线观看| 玖玖爱免费视频| 欧美v日韩v国产v| 91老司机福利在线| 国产一区免费| 亚洲在线日韩| 9.1成人看片免费版| 欧美日韩在线视频首页| 你懂的视频在线免费| 国产盗摄xxxx视频xxx69| 国产一区二区三区四区| 成人精品视频一区二区| 亚洲国产精品黑人久久久| 中文字幕永久在线观看| 久久激情五月丁香伊人| 老司机亚洲精品一区二区| 欧美高清中文字幕| 9久草视频在线视频精品| 精品国产一区二区三区四| 亚洲香蕉成人av网站在线观看| 九色成人搞黄网站| 自拍偷拍视频在线| 成人免费视频播放| 秋霞av一区二区三区| 在线一区二区日韩| 日韩精品久久久久久久软件91| 国产玉足脚交久久欧美| 久久一区二区三区四区| 影音先锋黄色网址| 欧美乱大交xxxxx另类电影| 乱亲女h秽乱长久久久| 成人一区二区三| 亚洲你懂的在线视频| 日本精品999| 国产精品男女猛烈高潮激情| 国产精品99在线观看| 在线观看免费视频黄| 色噜噜狠狠成人中文综合| 欧美日韩视频在线播放| 成人免费视频观看视频| 久久亚洲风情| 亚洲国产美女视频| 国产视频精品va久久久久久| 青草综合视频| 分分操这里只有精品| 国产色一区二区| 亚洲黄色a级片| 国产精品美女视频网站| 国精品一区二区| 国产视频三区四区| 精品国产乱码久久久久久蜜臀| 国产精品专区免费| 超级碰在线观看| 欧美国产日本视频| 人妻偷人精品一区二区三区| 国产精品美女网站| 亚洲一区日韩在线|