在這個cache everywhere的時代,在這我的人都會說分佈式緩存的時代,Memcached幾乎已成爲網站開發中的標配。html
做爲一名普通的coder,咱們在編寫緩存代碼的時候,不少狀況下可能都只是瞭解其基本原理,知道如何調用API,知道大概怎麼work around,而後測試經過上線,一般這樣作還真不會出事。git
然而看到這幾天評論猛烈的雄文由於所謂的代碼性能不高而被離職的程序員及其回帖,以及以前公司內部培訓發現居然有不少人不知道framework的緩存是天生的Thread Safe,實在忍不住,拋開非技術話題,也不討論代碼可讀性,就說說Memcached緩存的使用,用好用對其實並不容易,並且說不定就會有隱藏問題,真的太有總結的必要了。程序員
緩存的key有長度限制,key的組成有特定字符的限制。github
緩存的value必須能夠序列化,且緩存的單一value容量有大小限制,對於可序列化的value,應該千方百計儘可能規避某些特定數據結構,好比Hashtable,DataTable這些內部其實很是很是之複雜的數據結構。對於讀頻繁的操做來講,每次序列化和反序列化複雜數據結構的開銷可想而知。web
若是連分佈式緩存的key和value(尤爲是value)的通常限制都搞錯了,那麼使用緩存的後果極可能只是白白增長了網絡IO及序列化、反序列化的開銷,對系統性能提高固然是巨大的副作用。數據庫
這一點隱藏的也比較深,下面以應用普遍的EnyimMemcached爲例來簡單說明。緩存
一般咱們使用的客戶端每次實例化MemcachedClient對象內部都會初始化一個客戶端對象池(TCP鏈接池,客戶端命名爲ServerPool)。所謂TCP鏈接池就是將建立好的TCP鏈接(鏈接數一般按照配置來,生產環境的配置不會小於兩位數)初始化放在容器內,客戶端調用的時候能夠直接拿出已經存在的TCP鏈接來用,這樣能夠省去實時打開TCP鏈接的開銷。安全
由於有人喜歡using一下(固然包括樓主本身了),一看到MemcachedClient是繼承自IDisposable的,必須用using啊,而後就要new一個MemcachedClient對象,這樣客戶端內部也就不得再也不初始化一個TCP鏈接池。若是某個使用緩存的服務方法調用頻繁,很快你就會發現系統CPU飆升,頁面打開速度奇慢,直至不能正常訪問。服務器
咱們知道,分佈式緩存系統都有一個TCP鏈接上限的設置,不管如何,超過這個上限都有可能引起連環反應,這種反應毫無疑問是不良反作用。網絡
因此若是咱們誤用MemcachedClient,每次都new一個對象,那麼高併發狀況下效果就很是慘了,一方面web服務器由於TCP鏈接過多沒法正常訪問,另外一方面Memcached服務器也由於鏈接太多負載太重而性能變得極差,依賴Memcached的服務極可能短期內只接收到超時響應。
解決方案無比簡單,配置合適的TCP鏈接數,MemcachedClient對象單例便可。
最後還要重申選擇使用緩存的業務場景的重要性。這一點真的沒法說透,可是根據一些已有經驗,能夠提煉出兩條比較通用的緩存準則:
一、寫頻繁的數據不適合緩存;
二、讀頻繁而寫不頻繁的數據適合緩存。
果真正確的話都是廢話,上面兩條等於沒說。
怕大家說無聊,仍是要奉獻兩條本身使用緩存的主要準則,固然只是本身一家之言經驗之談,不可全信,切記,不然被總監勸退老子概不負責:
一、適合緩存的數據一般應該對外公開供(全部)人調用,私有的數據緩存多數狀況下是沒有意義的;
二、對準確性、實時性、安全性等要求極高的業務數據,你的數據可能不適合緩存。
順帶再提一下web開發中的性能問題。聽說若是一個網站有性能問題,那麼它必定會出現性能問題。數據庫、緩存、消息隊列、各類框架、com組件等等等等,這些web開發中的標配,有哪一個使用不當不會引起系統的性能問題呢?甚至你們習覺得常的拼接字符串在特定條件下都會形成系統崩潰。咱們也知道生產環境就像國際政治同樣錯綜複雜波譎雲詭,測試環境、UAT環境經過並不能保證系統諸事無虞,應該時刻認識到coding無小事,不然一個疏忽就有可能形成生產環境發生悲劇乃至慘劇。