【memcache緩存專題(1)】memcache的介紹與應用場景

簡介

Memcached是一個高性能的分佈式的內存對象緩存系統,目前全世界很多人使用這個緩存項目來構建本身大負載的網站,來分擔數據庫的壓力,經過在內存裏維護一個統一的巨大的hash表,它可以用來存儲各類格式的數據,包括圖像、視頻、文件以及數據庫檢索的結果等。簡單的說就是將數據調用到內存中,而後從內存中讀取,從而大大提升讀取速度。php

MemCache的工做流程以下:先檢查客戶端的請求數據是否在memcached中,若有,直接把請求數據返回,再也不對數據庫進行任何操做;若是請求的數據不在memcached中,就去查數據庫,把從數據庫中獲取的數據返回給客戶端,同時把數據緩存一份到memcached中(memcached客戶端不負責,須要程序明確實現);每次更新數據庫的同時更新memcached中的數據,保證一致性;當分配給memcached內存空間用完以後,會使用LRU(Least Recently Used,最近最少使用)策略加上到期失效策略,失效數據首先被替換,而後再替換掉最近未使用的數據。html

Memcached是以守護程序(監聽)方式運行於一個或多個服務器中,隨時會接收客戶端的鏈接和操做。默認監聽端口爲11211。前端

在 Memcached中能夠保存的item數據量是沒有限制的,只要內存足夠 。
Memcached單進程在32位系統中最大使用內存爲2G,若在64位系統則沒有限制,這是因爲32位系統限制單進程最多可以使用2G內存,要使用更多內存,能夠分多個端口開啓多個Memcached進程,最大30天的數據過時時間,設置爲永久的也會在這個時間過時,常量REALTIME_MAXDELTA 60*60*24*30控制。
最大鍵長爲250字節,大於該長度沒法存儲,常量KEY_MAX_LENGTH 250控制.
單個item最大數據是1MB,超過1MB數據不予存儲,常量POWER_BLOCK 1048576進行控制.但通常都是存儲一些文本,如新聞列表等等,這個值足夠了redis

memcached 用 slab allocator 機制來管理內存(在本專題的後續文章中會專門說這個內存機制的).它是默認的slab大小最大同時鏈接數是200,經過 conn_init()中的freetotal進行控制,最大軟鏈接數是1024,經過
settings.maxconns=1024 進行控制跟空間佔用相關的參數:settings.factor=1.25, settings.chunk_size=48, 影響slab的數據佔用和步進方式。算法

memcached是一種無阻塞的socket通訊方式服務,基於libevent庫,因爲無阻塞通訊,對內存讀寫速度很是之快
memcached分服務器端和客戶端,能夠配置多個服務器端和客戶端,應用於分佈式的服務很是普遍。
memcached做爲小規模的數據分佈式平臺是十分有效果的。
memcached是鍵值一一對應,key默認最大不能超過128個字節,value默認大小是1M,也就是一個slabs,若是要存2M的值(連續的),不能用兩個slabs,由於兩個slabs不是連續的,沒法在內存中 存儲,故須要修改slabs的大小,多個key和value進行存儲時,即便這個slabs沒有利用完,那麼也不會存放別的數據。sql

memcached已經能夠支持C/C++、Perl、PHP、Python、Ruby、Java、C#、Postgres、Chicken Scheme、Lua、MySQL和Protocol等語言客戶端。數據庫

應用場景

使用Memcache的網站通常流量都是比較大的,爲了緩解數據庫的壓力,讓Memcache做爲一個緩存區域,把部分信息保存在內存中,在前端可以迅速的進行存取。而且經過memcache的時效expire特性,還能夠更簡單的完成一些功能,我總結以下:數組

應用場景一: 緩解數據庫壓力,提升交互速度。緩存

在開發中不論是基於框架的面向對象開發,仍是面向過程開發,數據模型必定是要通過封裝後再使用的,這樣咱們就能夠對程序作統一處理,好比在程序開發初期,咱們沒用memcache或者redis來作緩存,咱們把從數據庫裏面取數據通通使用query($sql)方法來讀數據;安全

/**
 * 數據庫查詢僞代碼,僅僅是提供一個思路
 * @param  string   $sql     sql語句,好比select * form sc_users;
 * @param  int      $expire  緩存失效時間
 * @param  int      $type    1直接從數據庫裏面讀取,0先走緩存,再走數據庫
 * @return {[type]}         [description]
 */
public function query($sql,$expire=300,$type=0){
  if($type == 1){
    return '直接從數據庫裏面取出來';
  }

  $key = md5($sql); //以md5後的sql做爲key
  $result = $this -> mem -> get($key); 
  
  //若是緩存裏面沒有
  if(empty($result)){
    $data = '從數據庫裏面取到數據';
    //放入緩存
    $this -> mem -> add($key,$data,MEMCACHE_COMPRESSED,$expire); //$data是個數組,因此要序列化壓縮一下
    return $data;
  }

  //若是有的話就直接返回;
  return $result; 
}

它的一個總原則是將常常須要從數據庫讀取的數據緩存在memcached中。這些數據也分爲幾類:

1、常常被讀取而且實時性要求不強能夠等到自動過時的數據。例如網站首頁最新文章列表、某某排行等數據。也就是雖然新數據產生了,但對用戶體驗不會產生任何影響的場景。
這類數據就使用典型的緩存策略,設置一過合理的過時時間,當數據過時之後再從數據庫中讀取。固然你得制定一個緩存清除策略,便於編輯或者其它人員能立刻看到效果。

2、常常被讀取而且實時性要求強的數據。好比用戶的好友列表,用戶文章列表,用戶閱讀記錄等。
這類數據首先被載入到memcached中,當發生更改(添加、修改、刪除)時就清除緩存。在緩存的時候,我將查詢的SQL語句md5()獲得它的 hash值做爲key,結果數組做爲值寫入memcached,而且將該SQL涉及的table_name以及hash值配對存入memcached中。 當更改了這個表時,我就將與此表相配對的key的緩存所有刪除。

3、統計類緩存,好比文章瀏覽數、網站PV等
此類緩存是將在數據庫的中來累加的數據放在memcached來累加。獲取也經過memcached來獲取。但這樣就產生了一個問題,若是memcached服務器down 掉的話這些數據就有可能丟失,因此通常使用memcached的永固性存儲,這方面新浪使用memcachedb。

4、活躍用戶的基本信息或者某篇熱門文章。
此類數據的一個特色就是數據都是一行,也就是一個一維數組,當數據被update時(好比修改暱稱、文章的評論數),在更改數據庫數據的同時,使用Memcache::replace替換掉緩存裏的數據。這樣就有效了避免了再次查詢數據庫。

5、session數據
使用memcached來存儲session的效率是最高的。memcached自己也是很是穩定的,不太用擔憂它會忽然down掉引發session數據的丟失,即便丟失就從新登陸了,也沒啥。

6、冷熱數據交互
在作高訪問量的sns應用,好比貼吧和論壇,因爲其數據量大,每每採用了分表分庫的策略,但真正的熱數據僅僅是前兩三頁的100條數據,這時,咱們就能夠把這100條數據,在寫進數據庫以後,同時做爲memcache的緩存熱數據來使用。

經過以上的策略數據庫的壓力將會被大大減輕。檢驗你使用memcached是否得當的方法是查看memcached的命中率。有些策略好的網站的命中率能夠到達到90%以上。後續本專題也會討論一下memcache的分佈式算法,提升其命中率;

應用場景二: 秒殺功能。
其實,本場景嚴格的說應該也屬於場景一,單獨拎出來講是因爲其普遍的應用性。
一我的下單,要牽涉數據庫讀取,寫入訂單,更改庫存,及事務要求, 對於傳統型數據庫來講,壓力是巨大的。
能夠利用 memcached 的 incr/decr 功能, 在內存存儲 count 庫存量, 秒殺 1000 臺每人搶單主要在內存操做,速度很是快,搶到 count < =1000 的號人,得一個訂單號,這時再去另外一個頁面慢慢支付。

應用場景三:中繼 MySQL 主從延遲數據

MySQL 在作 replication 時,主從複製之間必然要經歷一個複製過程,即主從延遲的時間.
尤爲是主從服務器處於異地機房時,這種狀況更加明顯.
好比facebook 官方的一篇技術文章,其加州的主數據中心到弗吉尼亞州的主從同步延期達到70ms;

考慮以下場景:
①: 用戶 U 購買電子書 B, insert into Master (U,B);
②: 用戶 U 觀看電子書 B, select 購買記錄[user=’A’,book=’B’] from Slave.
③: 因爲主從延遲,第②步中無記錄,用戶無權觀看該書.
這時,能夠利用 memached 在 master 與 slave 之間作過渡(以下圖):

QQ圖片20151007125726.png-51.2kB

①: 用戶 U 購買電子書 B, memcached->add(‘U:B’,true)
②: 主數據庫 insert into Master (U,B);
③: 用戶 U 觀看電子書 B, select 購買記錄[user=’U’,book=’B’] from Slave.
若是沒查詢到,則 memcached->get(‘U:B’),查到則說明已購買但 Slave 延遲.
④: 因爲主從延遲,第②步中無記錄,用戶無權觀看該書.

不適用memcached的業務場景

  1. 緩存對象的大小大於1MB
    Memcached自己就不是爲了處理龐大的多媒體(large media)和巨大的二進制塊(streaming huge blobs)而設計的。

  2. key的長度大於250字符(因此咱們把一些key先md5再存儲)。

  3. 應用運行在不安全的環境中Memcached爲提供任何安全策略,僅僅經過telnet就能夠訪問到memcached。若是應用運行在共享的系統上,須要着重考慮安全問題。

  4. 業務自己須要的是持久化數據。

Memcache的安全

只說一下思路:
把memcached的端口給禁止掉(這時只能本ip訪問),讓其餘ip的使用者只能經過對外開放的80端口訪問PHP腳本文件,再經過PHP的腳本文件去訪問memcache;

iptables -a input -p 協議 -s 能夠訪問ip -dport 端口 -j ACCEPT

擴展閱讀

Memcache應用場景介紹,說明[zz]:
http://www.cnblogs.com/literoad/archive/2012/12/23/2830178.html

相關文章
相關標籤/搜索