1 Memcached 介紹
Memcached 是一個高性能的分佈式內存對象緩存系統,用於動態Web應用以減輕數據庫負載。它通過在內存中緩存數據和對象來減少讀取數據庫的次數,從而提供動態、數據庫驅動網站的速度。Memcached基於一個存儲鍵/值對的hashmap。其守護進程(daemon )是用C寫的,但是客戶端可以用任何語言來編寫,並通過memcached協議與守護進程通信。
Memcached需要有緩存服務端,採用java編程的話還需要memcached.jar,這就是java中實現memcached服務的插件。
2 使用Memcached目的
研究這個東東主要是爲了解決在項目中,由於信息過多,當用戶查詢數據時(目前當天查詢的都是前一天的數據),由於數據量過大,並且大併發情況下數據庫頻繁讀寫造成速度慢的問題。所以就想通過使用Memcached解決這一問題。
3 memcached原理及工作機制
Memcache是danga.com的一個項目,最早是爲 LiveJournal 服務的,目前全世界不少人使用這個緩存項目來構建自己大負載的網站,來分擔數據庫的壓力。
它可以應對任意多個連接,使用非阻塞的網絡IO。由於它的工作機制是在內存中開闢一塊空間,然後建立一個HashTable,Memcached自管理這些HashTable。
4 準備過程
在開發前,要準備有:
memcached-1.2.6-win32-bin.zip windows下服務器
memcached-1.2.6-win32-src.zip windows 下服務器源碼(是C語言哦,親)
memcached-1.2.6.tar.gz linux 下服務器
java_memcached-release_2.5.1.jar java 客戶端 JAR包
5 服務器安裝過程
首先解壓memcached-1.2.6-win32-bin.zip到某一盤下,然後使用命令、或者直接雙擊,運行。相當於就已經安裝好memcached服務器了。並且啓動了服務。它的默認端口是:11211(不建議修改)
打開控制面板-管理工具-服務:
此時可以訪問一下服務器:打開-運行-cmd-telnet 127.0.0.1 11211
輸入命令stats
這裏顯示了很多狀態信息,下邊詳細解釋每個狀態項:
1. pid: memcached服務進程的進程ID
2. uptime: memcached服務從啓動到當前所經過的時間,單位是秒。
3. time: memcached服務器所在主機當前系統的時間,單位是秒。
4. version: memcached組件的版本。這裏是我當前使用的1.2.6。
5. pointer_size:服務器所在主機操作系統的指針大小,一般爲32或64.
6. curr_items:表示當前緩存中存放的所有緩存對象的數量。不包括目前已經從緩存中刪除的對象。
7. total_items:表示從memcached服務啓動到當前時間,系統存儲過的所有對象的數量,包括目前已經從緩存中刪除的對象。
8. bytes:表示系統存儲緩存對象所使用的存儲空間,單位爲字節。
9. curr_connections:表示當前系統打開的連接數。
10. total_connections:表示從memcached服務啓動到當前時間,系統打開過的連接的總數。
11. connection_structures:表示從memcached服務啓動到當前時間,被服務器分配的連接結構的數量,這個解釋是協議文檔給的,具體什麼意思,我目前還沒搞明白。
12. cmd_get:累積獲取數據的數量,這裏是3,因爲我測試過3次,第一次因爲沒有序列化對象,所以獲取數據失敗,是null,後邊有2次是我用不同對象測試了2次。
13. cmd_set:累積保存數據的樹立數量,這裏是2.雖然我存儲了3次,但是第一次因爲沒有序列化,所以沒有保存到緩存,也就沒有記錄。
14. get_hits:表示獲取數據成功的次數。
15. get_misses:表示獲取數據失敗的次數。
16. evictions:爲了給新的數據項目釋放空間,從緩存移除的緩存對象的數目。比如超過緩存大小時根據LRU算法移除的對象,以及過期的對象。
17. bytes_read:memcached服務器從網絡讀取的總的字節數。
18. bytes_written:memcached服務器發送到網絡的總的字節數。
19. limit_maxbytes:memcached服務緩存允許使用的最大字節數。這裏爲67108864字節,也就是是64M.與我們啓動memcached服務設置的大小一致。
20. threads:被請求的工作線程的總數量。這個解釋是協議文檔給的,具體什麼意思,我目前還沒搞明白。
6 客戶端開發過程(分爲2種)
第1種:不使用spring(直接在static 裏面初始化連接。)
1 加載java_memcached-release_2.5.1.jar包
2 編寫MemcachedUtil 分佈式緩存工具類
3 創建需要緩存的對象(必須要序列化對象)
對於普通的POJO而言,如果要進行存儲的話,那麼比如讓其實現java.io.Serializable接口,因爲memcached是一個分佈式的緩存服務器,多臺服務器間進行數據共享需要將對象序列化的,所以必須實現該接口,否則會報錯的。緩存中獲取的對象是存入對象的一個副本,對獲取對象的修改並不能真正的修改緩存中的數據,而應該使用其提供的replace等方法來進行修改。
4 使用緩存(如果在緩存有效期內,則數據就從緩存中查詢,如果不在緩存有效期內,意思就是過期了,則就從數據庫中查詢)
5 緩存過期時間的設置
過期時間有兩種格式:
1. 相對時間:多長時間,給出過期的時間長度
2. 絕對時間:到期時間,給出過期的最後期限
相對時間時,返回的值是:服務器當前時間之後的exptime - process_started秒
絕對時間時,返回的值是:服務器當前時間之後的(exptime -服務器當前時間) -process_started秒。
可以看到,如果Client和Server時間不一致,使用絕對時間很容易導致緩存過期。
所以使用相對時間是比較安全的做法。
服務端的處理
時間處理源代碼【memcached.c】如下:
#define REALTIME_MAXDELTA60*60*24*30 //定義30天的秒數
static rel_time_t realtime(const time_texptime) {
if(exptime == 0) return 0;
if(exptime > REALTIME_MAXDELTA){ //超過30天,是絕對時間
if(exptime <=process_started) //小於進程啓動日期
return(rel_time_t)1; //
return(rel_time_t)(exptime - process_started); // 返回進程啓動之後的時間差
}else{ //不超過30天,是相對時間
return(rel_time_t)(exptime +current_time); // exptime + (tvsec -process_started)
}
}
OK,結束!
第2種方法:(使用spring配置,方便之後擴展)
1 同樣加載JAR包java_memcached-release_2.5.1.jar
2 封裝memcached緩存。建立接口IMemcachedClient
實現類MemcachedClientImpl.java
3 在spring的核心配置文件applicationContext.xml中配置
4 創建需要緩存的對象。
5 使用memcached的緩存
OK,結束!