一区二区久久-一区二区三区www-一区二区三区久久-一区二区三区久久精品-麻豆国产一区二区在线观看-麻豆国产视频

使用緩存的9大誤區(qū)(上)

  如果說要對一個站點或者應(yīng)用程序經(jīng)常優(yōu)化,可以說緩存的使用是最快也是效果最明顯的方式。一般而言,我們會把一些常用的,或者需要花費大量的資源或時間而產(chǎn)生的數(shù)據(jù)緩存起來,使得后續(xù)的使用更加快速。

  如果真要細說緩存的好處,還真是不少,但是在實際的應(yīng)用中,很多時候使用緩存的時候,總是那么的不盡人意。換句話說,假設(shè)本來采用緩存,可以使得性能提升為100(這里的數(shù)字只是一個計量符號而已,只是為了給大家一個“量”的體會),但是很多時候,提升的效果只有80,70,或者更少,甚至還會導(dǎo)致性能嚴重的下降,這個現(xiàn)象在使用分布式緩存的時候尤為突出。

  在本篇文章中,我們將為大家講述導(dǎo)致以上問題的9大癥結(jié),并且給出相對應(yīng)的解決方案。文章以.NET為例子進行代碼的演示,對于來及其他技術(shù)平臺的朋友也是有參考價值的,只要替換相對應(yīng)的代碼就行了!

  為了使得后文的闡述更加的方便,也使得文章更為的完整,我們首先來看看緩存的兩種形式:本地內(nèi)存緩存,分布式緩存。

  首先對于本地內(nèi)存緩存,就是把數(shù)據(jù)緩存在本機的內(nèi)存中,如下圖1所示:

  從上圖中可以很清楚的看出:

  • 應(yīng)用程序把數(shù)據(jù)緩存在本機的內(nèi)存,需要的時候直接去本機內(nèi)存進行獲取。
  • 對于.NET應(yīng)用而言,在獲取緩存中的數(shù)據(jù)的時候,是通過對象的引用去內(nèi)存中查找數(shù)據(jù)對象的,也就說,如果我們通過引用獲取了數(shù)據(jù)對象之后,我們直接修改這個對象,其實我們真正的是在修改處于內(nèi)存中的那個緩存對象。

  對于分布式的緩存,此時因為緩存的數(shù)據(jù)是放在緩存服務(wù)器中的,或者說,此時應(yīng)用程序需要跨進程的去訪問分布式緩存服務(wù)器,如圖2:

  不管緩存服務(wù)器在哪里,因為涉及到了跨進程,甚至是跨域訪問緩存數(shù)據(jù),那么緩存數(shù)據(jù)在發(fā)送到緩存服務(wù)器之前就要先被序列化,當要用緩存數(shù)據(jù)的時候,應(yīng)用程序服務(wù)器接收到了序列化的數(shù)據(jù)之后,會將之反序列化。序列化與反序列化的過程是非常消耗CPU的操作,很多問題就出現(xiàn)在這上面。

  另外,如果我們把獲取到的數(shù)據(jù),在應(yīng)用程序中進行了修改,此時緩存服務(wù)器中的原先的數(shù)據(jù)是沒有修改的,除非我們再次將數(shù)據(jù)保存到緩存服務(wù)器。請注意:這一點和之前的本地內(nèi)存緩存是不一樣的。

  對于緩存中的每一份數(shù)據(jù),為了后文的講述方面,我們稱之為“緩存項“。

  普及完了這兩個概念之后,我們就進入今天的主題:使用緩存常見的9大誤區(qū):

  1. 太過于依賴.NET默認的序列化機制
  2. 緩存大對象
  3. 使用緩存機制在線程間進行數(shù)據(jù)的共享
  4. 認為調(diào)用緩存API之后,數(shù)據(jù)會被立刻緩存起來
  5. 緩存大量的數(shù)據(jù)集合,而讀取其中一部分
  6. 緩存大量具有圖結(jié)構(gòu)的對象導(dǎo)致內(nèi)存浪費
  7. 緩存應(yīng)用程序的配置信息
  8. 使用很多不同的鍵指向相同的緩存項
  9. 沒有及時的更新或者刪除再緩存中已經(jīng)過期或者失效的數(shù)據(jù)

  下面,我們就每一點來具體的看看!

  太過于依賴.NET默認的序列化機制

  當我們在應(yīng)用中使用跨進程的緩存機制,例如分布式緩存memcached或者微軟的AppFabric,此時數(shù)據(jù)被緩存在應(yīng)用程序之外的進程中。每次,當我們要把一些數(shù)據(jù)緩存起來的時候,緩存的API就會把數(shù)據(jù)首先序列化為字節(jié)的形式,然后把這些字節(jié)發(fā)送給緩存服務(wù)器去保存。同理,當我們在應(yīng)用中要再次使用緩存的數(shù)據(jù)的時候,緩存服務(wù)器就會將緩存的字節(jié)發(fā)送給應(yīng)用程序,而緩存的客戶端類庫接受到這些字節(jié)之后就要進行反序列化的操作了,將之轉(zhuǎn)換為我們需要的數(shù)據(jù)對象。

  另外還有三點需要注意的就是:

  • 這個序列化與反序列化的機制都是發(fā)生在應(yīng)用程序服務(wù)器上的,而緩存服務(wù)器只是負責保存而已。
  • .NET中的默認使用的序列化機制不是最優(yōu)的,因為它要使用反射機制,而反射機制是是非常耗CPU的,特別是當我們緩存了比較復(fù)雜的數(shù)據(jù)對象的時候。

  基于這個問題,我們要自己選擇一個比較好的序列化方法來盡可能的減少對CPU的使用。常用的方法就是讓對象自己來實現(xiàn)ISerializable接口。

  首先我們來看看默認的序列化機制是怎么樣的。如圖3:

  然后,我們自己來實現(xiàn)ISerializable接口,如下圖4所示:

  我們自己實現(xiàn)的方式與.NET默認的序列化機制的最大區(qū)別在于:沒有使用反射。自己實現(xiàn)的這種方式速度可以是默認機制的上百倍。

  可能有人認為沒有什么,不就是一個小小的序列化而已,有必要小題大做么?

  在開發(fā)一個高性能應(yīng)用(例如網(wǎng)站)而言,從架構(gòu),到代碼的編寫,以及后面的部署,每一個地方都需要優(yōu)化。一個小問題,例如這個序列化的問題,初看起來不是問題,如果我們站點應(yīng)用的訪問量是百萬,千萬,甚至更高級別的,而這些訪問需要去獲取一些公共的緩存的數(shù)據(jù),這個之前所謂的小問題就不小了!

  下面,我們來看第二個誤區(qū)。

  緩存大對象

  有時候,我們想要把一些大對象緩存起來,因為產(chǎn)生一次大對象的代價很大,我們需要產(chǎn)生一次,盡可能的多次使用,從而提升響應(yīng)。

  提到大對象,這里就很有必要對其進行一個比較深入的介紹了。在.NET中,所謂的大對象,就是指的其占用的內(nèi)存大于了85K的對象,下面通過一個比較將問題說清楚。

  如果現(xiàn)在有一個Person類的集合,定義為List<Person>,每個Person對象占用1K的內(nèi)存,如果這個Person集合中包含了100個Person對象實例,那么這個集合是否是大對象呢?

  回答是:不是!

  因為集合中只是包含的Person對象實例的引用而言,即,在.NET的托管堆上面,這個Person集合分配的內(nèi)存大小也就是100個引用的大小而言。

  然后,對于下面的這個對象,就是大對象了: byte[] data = new byte[87040](85 * 1024 = 87040)。

  說到了這里,那就就談?wù)?,為什么說:產(chǎn)生一次大對象的代價很大。

  因為在.NET中,大對象是分配在大對象托管堆上面的(我們簡稱為“大堆”,當然,還有一個對應(yīng)的小堆),而這個大堆上面的對象的分配機制和小堆不一樣:大堆在分配的時候,總是去需找合適的內(nèi)存空間,結(jié)果就是導(dǎo)致出現(xiàn)內(nèi)存碎片,導(dǎo)致內(nèi)存不足!我們用一個圖來描述一下,如圖5所示:

  上圖非常明了,在圖5中:

  • 垃圾回收機制不會在回收對象之后壓縮大堆(小堆是壓縮的)。
  • 分配對象的時候,需要去遍歷大堆,去需找合適的空間,遍歷是要花成本的。
  • 如果某些空間小于85K,那么就不能分配了,只能白白浪費,也導(dǎo)致內(nèi)存碎片。

  講完了這些之后,我們言歸正傳,來看看大對象的緩存。

  正如之前講過,將對象緩存和讀取的時候是要進行序列化與反序列化的,緩存的對象越大(例如,有1M等),整個過程中就消耗更多的CPU。

  對于這樣的大對象,要看它使用的是否很頻繁,是否是公用的數(shù)據(jù)對象,還是每個用戶都要產(chǎn)生的。因為我們一旦緩存了(特別在分布式緩存中),就需要同時消耗緩存服務(wù)器的內(nèi)存與應(yīng)用程序服務(wù)器的CPU。如果使用的不頻繁,建議每次生成!如果是公用的數(shù)據(jù),那么建議多多的測試:將生產(chǎn)大對象的成本與緩存它的時候消耗的內(nèi)存和CPU的成本進行比較,選擇成本小的!如果是每個用戶都要產(chǎn)生的,看看是否可以分解,如果實在不能分解,那么緩存,但是及時的釋放!

  使用緩存機制在線程間進行數(shù)據(jù)的共享

  當數(shù)據(jù)放在緩存中的時候,我們程序的多個線程都可以訪問這個公共的區(qū)域。多個線程在訪問緩存數(shù)據(jù)的時候,會產(chǎn)生一些競爭,這也是多線程中常常發(fā)生的問題。

  下面我們分別從本地內(nèi)存緩存與分布式緩存兩個方面介紹競爭的帶來的問題。

  看下面的一段代碼:

  對于本地內(nèi)存緩存,對于上面的代碼,當這個三個線程運行起來之后,在線程1中,item的值很多時候可能為1,線程2可能是2,線程3可能是3。當然,這不一定!只是大多數(shù)情況下的可能值!

  如果是對于分布式緩存,就不好說了!因為數(shù)據(jù)的修改不是立刻發(fā)生在本機的內(nèi)存中的,而是經(jīng)過了一個跨進程的過程。

  有一些緩存模塊已經(jīng)實現(xiàn)了加鎖的方式來解決這個問題,例如AppFabric。大家在修改緩存數(shù)據(jù)的時候要特別注意這一點。

  認為調(diào)用緩存API之后,數(shù)據(jù)會被立刻緩存起來

  有時候,當我們調(diào)用了緩存的API之后,我們就會認為:數(shù)據(jù)已經(jīng)被換成了,之后就可以直接讀取緩存中的數(shù)據(jù)。盡管情況很多時候如此,但是不是絕對的!很多的問題就是這樣產(chǎn)生的!

  我們通過一個例子來講解。

  例如,對于一個ASP.NET 應(yīng)用而言,如果我們在一個按鈕的Click事件中調(diào)用了緩存API,然后在頁面呈現(xiàn)的時候,就去讀取緩存,代碼如下:

  上面的代碼照道理來說是對的,但是會發(fā)生問題。按鈕點擊之后回傳頁面,然后呈現(xiàn)頁面的時候顯示數(shù)據(jù),流程沒有問題。但是沒有考慮到這樣一個問題:如果服務(wù)器的內(nèi)存緊張,而導(dǎo)致進行服務(wù)器內(nèi)存的回收,那么很有可能緩存的數(shù)據(jù)就沒有了!

  這里有朋友就要說了:內(nèi)存回收這么快?

  這主要看我們的一些設(shè)置和處理。

  一般而言,緩存機制都是會設(shè)置絕對過期時間與相對過期時間,二者的區(qū)別,大家應(yīng)很清楚,我這里不多說。對于上面的代碼而言,如果我們設(shè)置的是絕對過期時間,假設(shè)1分鐘,如果頁面處理的非常慢,時間超過了1分鐘,那么等到呈現(xiàn)的時候,可能緩存中的數(shù)據(jù)已經(jīng)沒有了!

  有時候,即使我們在第一行代碼中緩存了數(shù)據(jù),那么也許在第三行代碼中,我們?nèi)ゾ彺孀x取數(shù)據(jù)的時候,就已經(jīng)沒有了。這或許是因為在服務(wù)器內(nèi)存壓力很大的,緩存機制將最少訪問的數(shù)據(jù)直接清掉?;蛘?a href=/yuedu/fuwuqi/ target=_blank class=infotextkey>服務(wù)器CPU很忙,網(wǎng)絡(luò)也不好,導(dǎo)致數(shù)據(jù)沒有被即使的序列化保存到緩存服務(wù)器中。

  另外,對于ASP.NET而言,如果使用了本地內(nèi)存緩存,那么,還涉及到IIS的配置問題(對緩存內(nèi)存的限制),我們有機會專門為大家分享這方面的知識。

  所以,每次在使用緩存數(shù)據(jù)的時候,要判斷是否存在,不然,會有很多的“找不到對象”的錯誤,產(chǎn)生一些我們認為的“奇怪而又合理的現(xiàn)象”。

  關(guān)于作者

  汪洋,現(xiàn)任惠普架構(gòu)師、信息分析師《NET應(yīng)用架構(gòu)設(shè)計:模式、原則與實踐》作者。上海益思研發(fā)管理咨詢有限公司首席軟件架構(gòu)專家,軟件咨詢組副組長。

NET技術(shù)使用緩存的9大誤區(qū)(上),轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 国产爆操 | 亚洲一区二区三区在线网站 | 国产精品一区二区在线播放 | 欧美xxxx另类 | 国产精品福利在线观看入口 | 无码精品日韩中文字幕 | 国产综合变态自虐重口另类 | 激情综合五月天 | 亚洲丝袜一区二区 | 精品在线91 | 欧美亚洲图片小说 | 五月婷六月 | 91在线播放网站 | 国产专区青青草原亚洲 | 中文字幕色网站 | 欧美日韩一区二区亚洲 | 麻豆娜娜 | 色婷婷5月| 国产最新精品视频 | 日韩狠狠操| 韩国免费特一级毛片 | 天天添| 国内精品久久久久久野外 | 一区精品麻豆经典 | 国产成人精品午夜二三区 | 国产精品久久久久久久专区 | 国内精品美女久久久久 | 国产成人福利精品视频 | 日本精品久久久久久久 | 免费精品一区二区三区在线观看 | 欧美日韩亚洲另类人人澡 | 精品综合久久久久久97超人该 | 性天堂网 | 手机在线黄色 | 亚洲综合图片网 | 国产福利在线观看永久免费 | 91香蕉国产亚洲一区二区三区 | 在线观看www日本免费网站 | 国产三级国产精品国产普男人 | 国产精品视频一区二区三区w | 国产一区二区三区怡红院 |