帶你走進緩存世界

  我們搞程序的多多少少都了解點算法。總體來講,算法是什么?算法就是“時間”和“空間”的互換策略。我們常常考究一個算法的時間復雜度或空間復雜度,如果我們有絕對足夠的時間或空間,那么算法就不需要了,可惜這種條件是不存在的,只是在某些情況下相對來說我們不用去考慮其中一個。今天我們討論的“緩存”,自然就是“用空間換時間”的算法。 緩存就是把一些數據暫時存放于某些地方,可能是內存,也有可能硬盤。總之,目的就是為了避免某些耗時的操作。我們常見的耗時的操作,比如數據庫的查詢、一些數據的計算結果,或者是為了減輕服務器的壓力。其實減輕壓力也是因查詢或計算,雖然短耗時,但操作很頻繁,累加起來也很長,造成嚴重排隊等情況,服務器抗不住)

  概念性的東西暫就不說了,說多了都是故事。現在我們來談談各種緩存。

  初學.NET的朋友開始就會接觸到DataSet類,云里霧里的看著DataSet的例子程序,也不管是咋回事,用就是了。其實DataSet就是緩存,當我們去讀取一段數據集合的時候,如果每讀取一條數據就處理一條的話,那么我們的程序和數據庫會一直連接著。假如處理一條數據的耗時可以忽略不計,或者只有你一個人使用這個數據庫的話,那么數據庫一直連著也無所謂,我們寫代碼完全可以不用DataSet類。但是事實上不耗時不可能的,如果耗時嚴重的話,就會一直占用這數據庫連接,直到我們處理完畢。如果這種查詢過多,連接數就會占用過多,而且數據庫在某些操作時會鎖住表,這就會造成其他的請求等待,會出現查詢超時,程序異常等現象。所以,我們必須先把數據拿出來,再對這些數據進行相關的處理,盡早的關閉數據庫連接,好讓數據庫處理其他的請求。?所以,適時地選用DataSet或DataReader是比較重要的(說明:DataReader就是hold住連接的讀取方式)。

  你可能會迷惑,不知不覺中使用了緩存(DataSet),這都是.net幫你完成的事。可是,你可能還是不太清楚該如何使用緩存,或者說何時使用緩存。不用著急,我們一一來看。

  上面說過,我們緩存的數據無非就是一些數據庫的查詢、計算結果和頻繁查詢。那么,我們在實際開發中會碰到哪些這種數據呢??其實仔細想想這是非常常見的,比如用戶登錄后的個人資料,當他每次點擊連接后造成頁面刷新,我們總不能都要去重新查詢數據庫吧?我們常常用Session來存儲這個人的信息,當他退出系統后我們把Session清理掉,所以Session也是緩存,只不過他也是.NET給我們提供好的類,sorry,我又舉了一個你不想看到的例子,哈哈。其實Session是私有化的數據,Session的數據訪問必須通過SessionID(詳情我就不多言了,大家google下),還不足以說明緩存的意義。如果把這個問題延伸下去,假如我們開發的是一個多用戶的Blog系統,?每當我們訪問其中一個博客時都要去查詢這個博主的資料,假如A和B同時訪問一個博客時,最理想的狀態就是只查詢一次,而不是兩個人都去訪問數據庫!是不是呢?其實。。。是也不是!(故事里的事,說是就是,不是也是;說不是就不是,是也不是。?:)。之所以說不是,是因為假如我們的博客網站每天就幾個人訪問,而且一直發展不起來,我們就沒必要用緩存,因為使用緩存帶來了更多的開發復雜度,因為每當我們去更新博主的資料的時候不單單要更新數據庫的信息,我們還要去處理緩存。但是如果我們的博客訪問量非常大,就像博客園似的,如果再不緩存,那數據庫服務器早就Gameover了:),那么現在就來看怎么用緩存的吧。

  .Net?Framework提供了現成的緩存類供我們使用,常見的是?System.Web.HttpRuntime.Cache。每當我們去執行?BlogDataProvier.GetBlogInfo()方法時(假定這個方法是我們獲取博主信息的方法,顧名思義嘛),需要在查詢之前先從緩存獲取數據,假如數據不存在的話,再去數據庫獲取,并且把得到的結果存入緩存,并且返回該結果既可。下面我把這個方法的偽代碼寫出來,好讓從來沒用過緩存的朋友大致了解一下。

public class SqlDataProvider
{public static object GetBlogInfo(string username){//這里是從數據庫獲取BlogInforeturn null;}}public class BlogDataProvider
{public static object GetBlogInfo(string username){var cacheKey = "Blog_" + username;var blog = CacheHelper.Get(cacheKey);if (blog == null){blog = SqlDataProvider.GetBlogInfo(username);CacheHelper.Set(cacheKey, blog);}return blog;}
}
public class CacheHelper
{public static object Get(string key){return System.Web.HttpRuntime.Cache.Get(key);}public static void Set(string key, object value){System.Web.HttpRuntime.Cache.Insert(key, value);}
}

?

  緩存,兩個字道出了其實際意義,一個是“存”,我們剛剛存了;另一個是“緩”,暫緩,緩存一般只是用來暫時存儲,其命運都會被刪除或替換掉,所以緩存有個時效問題。如果你說你的數據永遠都不會過期,那么說真的,我建議你直接寫在代碼里就可以了。?

  上面的例子讓我們了解到了HttpCache類。看來我們可以用它來解決絕大部分的緩存問題,主要是公共數據的緩存(所謂公共數據就是你我都可以訪問的同一數據)。希望新手朋友捧著MSDN仔細學習該類的用法,真的很重要哦,不是嗎?

  開始我們說了“拿空間換時間”,目前只提到了緩存一些頻繁查詢的情況,犧牲空間緩存時間的明顯些的例子有嗎?沒問題,你看好咯!

  說之前先插一句,我們公司現在在招人,其中一道筆試題是介紹一下List<T>和Dictionary<TKey,TValue>的區別和用途。很遺憾,面試了很多人,只有一個同學回答的到位,其他的說什么的都有。你想好怎么回答了嗎?:)如果你看了下面發現和你現在想的一致而且你還需要找一份有挑戰的工作的話,給我消息哦。

  其實用List<T>,Dictionary<TKey,TValue>泛型就是用來迷魂人的,哈哈,就會有些同學往泛型上面扯,結果上當咯,我完全可以用ArrayList和Hashtable來問。

  List是什么數據結構?數組!而且是動態的數組,之所以動態就是可以視情況動態申請空間。Dictionary是什么結構?有的同學回答是字典。字典是什么數據結構??散列表!散列,一聽這名字就知道是散開分布的數據表。怎么個“散”法??自然是按照Key來散,每個Key對應一個Value,所以我們常叫做“鍵值對”,Key和Value是成對的。我們把Dictionary看作是一個數組,那么每個Key的hash值(什么是hash值?在.net里任何類型都有GetHashCode方法,返回int值,有木有),便是數組的下標,而該數組的元素值就是Value!所以我們在獲取Dictionary的某個Key的Value時,速度是非常快的,可以直接通過已知的下標拿到值,這個時間復雜度是O(1)。快不快啊?好快好快。但是,你有木有想到,所有的Key的hash值是按順序來的嗎?顯然不是,鬼知道你用的什么key,所以,Dictionary的這個數組很長很長,浪費了很多空位置,所以,那就是?空間?換?時間。當然GetHashCode的算法不同,Key對應的值的分布也有區別,有的比較緊密有的比較松散,常見的算法比如一致性hash算法。

dictionary的實際內存分布2011040511314628.jpg

  如上圖所示,dict的分布是不緊湊的,犧牲了很多空間,但可以最快速的找到數據,所以dict或hash或map等,不管什么叫什么類,總之都是hashtable,它們的用途主要就是查詢。所以,如果我們把博客按用戶名作key緩存起來的話,用戶訪問博客時都是使用的username,所以我們甚至不需要blogId,就可以拿到博主的信息,根本沒走數據庫。

  而list這種排列緊湊的數據集合一般用于批處理。當然還有兼顧空間和速度的數據結構,那就是樹結構,在查找時不需要所有數據都進行遍歷,時間復雜度一般是O(logn),而且空間是緊湊的,采用的是鏈表結構,而不是緊湊的數組。所以在時間和空間上都不比前兩者,但用途卻十分廣大,我們所用的數據庫的索引基本上都是用的樹。這樣既保證了占用空間小,查詢的速度也不慢。

  上面這一段我們介紹了hash表的基本原理,現在我們明白了緩存的優勢,在實際的項目使用中,我們除了使用系統提供的Cache類以外,完全可以自己嘗試寫緩存類,為什么不呢?呵呵。我們把一個變量斯static,然后再public,就等于是全局變量了,我們可以到處訪問到他,而且我們還要用dict,因為他足夠快!還不快動手去寫一個,回來再接著看!

?

  剛才提到了“緩”字,緩也有不同的策略,比如最常見的按時間緩存,在單位時間內該數據有效,每當訪問時都要判斷緩存的數據是否過期,再決定Get還是Remove。除了時間策略,還有使用熱度策略,由于內存有限,所以我們的緩存也不是無限申請的,是時候限制長度了。限制了長度就意味著有人能進來就得有人要出去。這就是Remove策略。我們可以對所有的緩存打上標記,來標記他的熱度,每次添加緩存的時候把熱度最低的緩存剔除掉(假如已經達到限制的話)。每次獲取緩存的時候給該緩存熱度+1。這是多人性化的設計,不是嗎??我上篇博文中已經貼出了這類的代碼。有興趣的朋友給你們個傳送門。

  我們繼續用博客園作例子,我們知道博客園的訪問量已經很大了(具體多大,俺不知道,反正以前發表評論經常超時,官方團隊解決后還發表博文說咋解決的,結果評論里一大票同學都說怎么不用緩存阿:)。??

  當網站訪問量達到一定程度后,一臺機器很難處理太多的httprequest,這個時候我們必須使用多臺機器。假如你的程序沒同時跑在多臺機器上的話,你對緩存的理解恐怕不會很深,因為誰都要會這種經歷:哎呀?sessio不能分布式阿??哎呀媽呀,我的緩存不能在兩臺機器上阿,這可咋整?!

  其實這也不能怪你,要怪就怪微軟吧。因為IIS,我們的web程序駐留在一個進程里,每個httprequest會有一個線程來處理,所以你甚至都沒用過多線程。害人啊,哈哈。但隨著項目經驗的增加,特別是大項目的歷練后,也沒什么了。之所以說是微軟的錯,是因為人家php阿,ruby阿,人家的服務端(apache,nginx等)都是多進程的。每個httprequest一個進程,總共開幾十個進程,處理并發。多進程就意味著數據共享問題,就像我們多臺機器的情況一樣。?這時候需要借助一個共享緩存進程來供其他的web服務進程來訪問獲取緩存。?這就是下面要說的?分布式緩存。

  如果說兩三年前你不知memcached為何物,或許情有可原,那時候還流行自己寫windows?service。但現在滿世界的NoSQL,MongoDB,Memcached,Redis,你再不知道的話,真該說多看看博客吧;看看新技術,你已經落后一個時代了。

  上面提到的這個名詞都是玩緩存的主。NoSQL是個新技術,NoSQL?DB現在很多種,MongoDB就是一種,MongoDB是介于傳統關系型數據庫和內存數據庫的雜交數據庫,現在也算是很熱門的數據庫。MemCached是著名的分布式緩存服務,而Redis(Remoting?Dictionary?Service),你懂了吧?!我們的緩存服務器可以用memcached或redis,Memcached是純內存的,重啟進程會丟失所有緩存,而redis可以把數據寫到硬盤里,各有各的優點吧。Redis更適合存經過計算過的數據。而且Redis支持豐富的數據類型(list\set\hash\string),這要比memcached更靈活些。?他們都有.net的Driver,還有相關的Example和UnitTest,可以官網下載看看。

  關于Redis的使用可以看代震軍大蝦的http://www.cnblogs.com/daizhj/archive/2011/02/21/1959511.html?

  隨著硬件的發展,內存的不斷增加,緩存的應用越來越多,現在各種NoSQL數據庫應用而生,我們也要緊跟腳步,學習新的理念。關于NoSQL我這里也不多介紹了,自己搜索。

  其他的緩存,比如頁面的緩存(OutputCache)我這里就不作介紹了,緩存其他同學補充。謝謝各位閱讀。歡迎大家交流,交流的方式希望是和諧的,最好不要有帶味的評論,帶來不好的討論氛圍,說錯誤的希望大家提出。

轉載于:https://www.cnblogs.com/mad/archive/2011/04/05/take_you_into_the_world_of_caching.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/378543.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/378543.shtml
英文地址,請注明出處:http://en.pswp.cn/news/378543.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

霍夫碼編碼(一種不等長,非前綴編碼方式)

霍夫曼編碼是一種不等長非前綴編碼方式&#xff0c;于1951年由MIT的霍夫曼提出。 用于對一串數字/符號編碼獲取最短的結果&#xff0c;獲取最大的壓縮效率。 特點&#xff1a;不等長、非前綴 等長式編碼 等長編碼&#xff0c;意思是對出現的元素采用相同位數的序號進行標定&a…

php調用shell腳本安全,從PHP調用的shell腳本問題

TLDR;我有一個shell腳本,從命令行運行時工作正常,但如果從PHP腳本中調用(通過Web訪問)則不行.在這兩種情況下,主叫用戶都是www-data.線路失敗是這樣的&#xff1a;openssl genrsa -des3 -out certs/$PCODE.key -passout env:PASSPHRASE 2048為什么會這樣&#xff1f;我該怎么調…

linux 運維基礎問題_Linux基礎能力問題和解答

linux 運維基礎問題This section contains Aptitude Questions and Answers on Linux Basics. 本節包含有關Linux基礎知識的 Aptitude問答。 1) There are the following statements that are given below, which of them are correct about Linux? Linux is system software…

JS 獲取瀏覽器信息,給出友情提示,避免部分兼容性問題

最近在做webform,瀏覽器兼容是個問題,這里我收集了一些獲取瀏覽器信息的資料,可以給一些用戶使用時,提示瀏覽器版本過低,讓升級版本用. 這樣會給開發的我們,省下很多用來調試兼容性的時間和精力. 本人就是這樣想的 ~  檢測瀏覽器及版本使用 JavaScript 檢測關于訪問者的瀏覽器…

兩欄 三欄的css

三欄格局 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns"http://www.w3.org/1999/xhtml" xml:lang"zh" lang"zh"><head pro…

06-機器學習(Haar+Adaboost實現人臉、人眼檢測)

機器學習是什么? 機器學習訓練樣本特征分類器&#xff0c;通過讓機器學習的方式&#xff0c;來達到某種功能的過程 深度學習是什么&#xff1f; 深度學習海量的學習樣本人工神經網絡 機器學習需要&#xff1a;樣本、特征、分類器、對訓練后的數據進行預測或檢驗 人臉樣本haar…

php xml表格形式輸出,PHP XML如何輸出nice格式

這里是代碼&#xff1a;$doc new DomDocument(1.0);// create root node$root $doc->createElement(root);$root $doc->appendChild($root);$signed_values array(a > eee, b > sd, c > df);// process one row at a timeforeach ($signed_values as $key &…

Opencv實戰【3】——圖像修復與圖像銳化(darling in the franxx)

目錄前言圖像修復圖像銳化darling in the franxx圖片總結前言 前天&#xff0c;在群里看見有人發了這張表情包&#xff1a; 感覺女主有點好看&#xff0c;然后問室友是啥番劇&#xff08;darling in the franxx&#xff09;&#xff0c;然后就去補番了&#xff0c;然后從晚上…

python 示例_Python date isoweekday()方法與示例

python 示例Python date.isoweekday()方法 (Python date.isoweekday() Method) date.isoweekday() method is used to manipulate objects of date class of module datetime. date.isoweekday()方法用于處理模塊日期時間的日期類的對象。 It uses a date class object and r…

07-機器學習(Hog+SVM實現小獅子識別)

一、SVM支持向量機 什么是SVM支持向量機&#xff1f; SVM支持向量機本質仍是一個分類器&#xff0c;其核心為尋求一個最優超平面最終實現分類&#xff0c;實現分類問題 在尋求超平面的時候有多種方式&#xff0c;可以使用若干條直線或曲線進行分類&#xff0c;這里使用的是直線…

Net Remoting基礎篇

一、Remoting基礎 什么是Remoting&#xff0c;簡而言之&#xff0c;我們可以將其看作是一種分布式處理方式。從微軟的產品角度來看&#xff0c;可以說Remoting就是DCOM的一種升 級&#xff0c;它改善了很多功能&#xff0c;并極好的融合到.Net平臺下。Microsoft .NET Remoting …

Maven3.0.5代理nexus

Nexus簡介 Nexus是Sonatype推出的強大Maven倉庫管理器產品&#xff0c;要比以前TSS上介紹的Artifactory要好使用的多&#xff0c;也是一個拆箱即用的Java App&#xff0c;內嵌Jetty容器和Java Wrapper做Windows服務&#xff0c;安裝簡單到解壓然后雙擊install即可。更詳細的幫助…

8253譯碼電路設計以及初始化編程講解

先驗知識回顧&#xff1a;知識點不清晰的時候可以查詢相關知識點。 https://blog.csdn.net/qq_42604176/article/details/105810973 需掌握的主要知識點 1、譯碼電路設計 2、初始化編程 例題1 在以 8086構成的最大方式系統中&#xff0c;有一片8254的端口地址分別為301H、3…

java安卓寫文件路徑,如何使用gradle作為構建系統,平臺Android配置Protobuf(Java)文件的輸出路徑?...

我正在努力解決以下問題&#xff1a;我有2個基于maven的java項目和1個基于gradle的Android項目 . 布局如下&#xff1a;Workspace/├── MavenProj1/├── MavenProj2/├── AndroidGradleProject1/├── Protos/所有這些的包結構很常見&#xff0c;比方說 com.example.* 所…

Java System類exit()方法及示例

系統類exit()方法 (System class exit() method) exit() method is available in java.lang package. exit()方法在java.lang包中可用。 exit() method is used to exit the currently running JVM (Java Virtual Machine). exit()方法用于退出當前正在運行的JVM(Java虛擬機)。…

基于圖像處理的數碼印花噴墨墨滴形狀規范的研究(Python+OpenCV+Mysql)

大體思路&#xff1a;由于墨滴的不同參數會對墨滴的形態產生一定的影響&#xff0c;故如果通過研究墨滴的形態則通過海量的數據就可以大概確定墨滴的各項參數指標的范圍。通過OpenCV對墨滴的噴出的形狀進行圖像處理&#xff0c;對墨滴圖像進行一系列的分析&#xff0c;通過一系…

ASP.NET 主題(Themes)FAQ

1、主題是什么 主題由一組元素組成&#xff1a;外觀、級聯樣式表 (CSS)、圖像和其他資源。主題將至少包含外觀。主題是在網站或 Web 服務器上的特殊目錄中定義的。主題是一組Web Control的屬性設置的集合&#xff0c;提供一種簡單的方法設置控件的樣式屬性。 主題只在Web Contr…

Head First HTML與CSS、XHTML++筆記(第四章 WEB鎮之旅 第五章 認識媒體)

第四章 鏈接&#xff08;詳解<a>元素&#xff09; 目標錨 在目標位置 <h2><a id"chai">contentTest</a></h2> 在需要鏈接位置 <a href"index.html#chai">See</a> 鏈接到自身的目標錨 <a href"#top"…

Opencv實戰【4】——圖片動漫化處理

博主聯系方式&#xff1a; QQ:1540984562 微信&#xff1a;wxid_nz49532kbh9u22 QQ交流群&#xff1a;750313950 目錄動漫化風格的特點處理手段代碼實現效果總結動漫化風格的特點 &#xff08;1&#xff09;動漫中的細節相對少&#xff1b; &#xff08;2&#xff09;動漫中的邊…

nextshort_Java掃描儀的nextShort()方法與示例

nextshort掃描器類的nextShort()方法 (Scanner Class nextShort() method) Syntax: 句法&#xff1a; public short nextShort();public short nextShort(int rad);nextShort() method is available in java.util package. nextShort()方法在java.util包中可用。 nextShort() …