天天躁日日躁狠狠躁AV麻豆-天天躁人人躁人人躁狂躁-天天澡夜夜澡人人澡-天天影视香色欲综合网-国产成人女人在线视频观看-国产成人女人视频在线观看

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

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

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

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

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

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

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

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

  對(duì)于分布式的緩存,此時(shí)因?yàn)榫彺娴臄?shù)據(jù)是放在緩存服務(wù)器中的,或者說(shuō),此時(shí)應(yīng)用程序需要跨進(jìn)程的去訪(fǎng)問(wèn)分布式緩存服務(wù)器,如圖2:

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

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

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

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

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

  下面,我們就每一點(diǎn)來(lái)具體的看看!

  太過(guò)于依賴(lài).NET默認(rèn)的序列化機(jī)制

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

  另外還有三點(diǎn)需要注意的就是:

  • 這個(gè)序列化與反序列化的機(jī)制都是發(fā)生在應(yīng)用程序服務(wù)器上的,而緩存服務(wù)器只是負(fù)責(zé)保存而已。
  • .NET中的默認(rèn)使用的序列化機(jī)制不是最優(yōu)的,因?yàn)樗褂梅瓷錂C(jī)制,而反射機(jī)制是是非常耗CPU的,特別是當(dāng)我們緩存了比較復(fù)雜的數(shù)據(jù)對(duì)象的時(shí)候。

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

  首先我們來(lái)看看默認(rèn)的序列化機(jī)制是怎么樣的。如圖3:

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

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

  可能有人認(rèn)為沒(méi)有什么,不就是一個(gè)小小的序列化而已,有必要小題大做么?

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

  下面,我們來(lái)看第二個(gè)誤區(qū)。

  緩存大對(duì)象

  有時(shí)候,我們想要把一些大對(duì)象緩存起來(lái),因?yàn)楫a(chǎn)生一次大對(duì)象的代價(jià)很大,我們需要產(chǎn)生一次,盡可能的多次使用,從而提升響應(yīng)。

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

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

  回答是:不是!

  因?yàn)榧现兄皇前腜erson對(duì)象實(shí)例的引用而言,即,在.NET的托管堆上面,這個(gè)Person集合分配的內(nèi)存大小也就是100個(gè)引用的大小而言。

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

  說(shuō)到了這里,那就就談?wù)劊瑸槭裁凑f(shuō):產(chǎn)生一次大對(duì)象的代價(jià)很大。

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

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

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

  講完了這些之后,我們言歸正傳,來(lái)看看大對(duì)象的緩存。

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

  對(duì)于這樣的大對(duì)象,要看它使用的是否很頻繁,是否是公用的數(shù)據(jù)對(duì)象,還是每個(gè)用戶(hù)都要產(chǎn)生的。因?yàn)槲覀円坏┚彺媪耍ㄌ貏e在分布式緩存中),就需要同時(shí)消耗緩存服務(wù)器的內(nèi)存與應(yīng)用程序服務(wù)器的CPU。如果使用的不頻繁,建議每次生成!如果是公用的數(shù)據(jù),那么建議多多的測(cè)試:將生產(chǎn)大對(duì)象的成本與緩存它的時(shí)候消耗的內(nèi)存和CPU的成本進(jìn)行比較,選擇成本小的!如果是每個(gè)用戶(hù)都要產(chǎn)生的,看看是否可以分解,如果實(shí)在不能分解,那么緩存,但是及時(shí)的釋放!

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

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

  下面我們分別從本地內(nèi)存緩存與分布式緩存兩個(gè)方面介紹競(jìng)爭(zhēng)的帶來(lái)的問(wèn)題。

  看下面的一段代碼:

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

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

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

  認(rèn)為調(diào)用緩存API之后,數(shù)據(jù)會(huì)被立刻緩存起來(lái)

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

  我們通過(guò)一個(gè)例子來(lái)講解。

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

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

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

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

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

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

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

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

  關(guān)于作者

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

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

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

主站蜘蛛池模板: 两百磅美女 | 三级全黄的视频在线观看 | 亚洲青青青网伊人精品 | 色综合99久久久国产AV | 小学生偷拍妈妈视频遭性教育 | 在线视频久久只有精品第一日韩 | vr亚洲成年网址在线观看 | 极品美女穴 | 日韩内射美女人妻一区二区三区 | 色拍拍噜噜噜久久蜜桃 | 国产成人精品三级在线 | 亚洲中久无码永久在线 | good神马电影伦理午夜 | 国产成人免费手机在线观看视频 | 国内精品自线在拍2020不卡 | 免费毛片视频网站 | 国产亚洲精品久久孕妇呦呦你懂 | 99久久网站 | 国产成人精品综合在线 | 亚洲色图在线观看视频 | 男男高h浪荡受h | 久久亚洲网站 | 久久大香萑太香蕉av | 超碰国产亚洲人人 | 97成人碰碰在线人妻少妇 | 国产精品高潮AV久久无码 | 伊人网伊人网 | 性绞姿始动作动态图 | 国精一区二区AV在线观看网站 | 成人精品视频在线 | 榴莲推广APP网站入口下载安装 | 国产色婷亚洲99精品AV | 国产99网站 | 国色天香社区视频免费高清3 | 麻豆第一区MV免费观看网站 | 校园纯肉H教室第一次 | 日韩精品无码久久一区二区三 | 国产成人免费a在线视频app | 国产精品人成在线播放新网站 | 国产午夜精品鲁丝片 | 69SEX久久精品国产麻豆 |