Memcached是一個自由開源的,高性能,分佈式內存對象緩存系統。 Memcached是一種基於內存的Key-Value存儲,用來存儲小塊的任意數據(字符串、對象)。這些數據能夠是數據庫調用、API調用或者是頁面渲染的結果。 Memcached簡潔而強大。它的簡潔設計便於快速開發,減輕開發難度,解決了大數據量緩存的不少問題。它的API兼容大部分流行的開發語言。 本質上,它是一個簡潔的key-value存儲系統。 通常的使用目的,是經過緩存數據庫查詢結果,減小數據庫訪問次數,以提升動態Web應用的速度、提升可擴展性。php
Memcached做爲高速運行的分佈式緩存服務器,具備如下的特色。html
Memcached的分佈式部署極其簡單,一般較小的應用一臺Memcached服務器就能夠知足需求,可是大中型項目可能就須要多臺Memcached服務器了,這就牽涉到一個分佈式部署的問題。對於多臺Memcached服務器,怎麼肯定一個數據應該保存到哪臺服務器呢?有兩種方案,一是普通Hash分佈,二是一致性Hash分佈。普通Hash分佈對於Memcached服務器數量固定的狀況推薦使用,比較簡單。可是當服務器數量發生改變時,問題就出來了。由於同一個KEY經Hash算法處理後,與服務器數量取模,會致使結果與服務器數量未變化時不一樣,這就致使以前保存的數據丟失。採起一致性Hash分佈能夠有效的解決這個問題,把丟失的數據減到最小(注意這裏並無說徹底不丟失)。算法
下面經過一個簡單的實例來講明Memcached的高性能,以及Memcached是如何工做的。數據源採用的是隨機生成的1500萬條記錄,經過控制檯程序來模擬用戶登陸的業務邏輯,若是首次登陸成功,則把用戶信息寫入Memcached緩存中,再次登陸時便可從緩存中取得用戶信息進行驗證。如下是詳細代碼過程:sql
數據操做接口:數據庫
1 namespace MemcachedLibrary 2 { 3 interface IDataOperator 4 { 5 //獲取數據庫鏈接 6 SqlConnection OpenConnection(); 7 //獲取用戶信息 8 void GetUserInfo(string user, string pass); 9 } 10 }
具體的登陸業務操做:緩存
1 public class SQLDataOperator : IDataOperator 2 { 3 //數據庫鏈接串 4 private const string connectKey = "server=DESKTOP-ALQLV05;database=db_TencentEmailInfo;uid=sa;pwd="; 5 6 //標記變量,標記是否已經緩存 7 private bool IsMemcachedFinished = false; 8 9 //獲取用戶信息 10 public void GetUserInfo(UserInfo user) 11 { 12 Stopwatch memcachedWatch = new Stopwatch(); 13 memcachedWatch.Start(); 14 15 //從Memcached中取得數據,初始化SockIOPool 16 SockIOPool pool = MemcachedMain.MemcachedInitialize(); 17 MemcachedClient client = MemcachedMain.GetMemcachedInstance(); 18 //檢查Memcached是否緩存了User信息 19 if (client.KeyExists("user") && client.KeyExists("pass")) 20 { 21 if (user.User == client.Get("user").ToString() && user.Pass == client.Get("pass").ToString()) 22 { 23 Debug.WriteLine("登陸成功!已從Memcached中取得用戶信息!"); 24 } 25 IsMemcachedFinished = true; 26 } 27 memcachedWatch.Stop(); 28 Debug.WriteLine("Memcached取得用戶信息耗時:" + memcachedWatch.ElapsedMilliseconds + "毫秒"); 29 30 //若是Memcached中已經緩存User信息,則無需到數據庫中檢索數據,提升性能 31 if (IsMemcachedFinished) 32 { 33 return; 34 } 35 36 37 //若是Memcached中沒有緩存過數據,則從數據庫中取得數據,並將結果緩存到Memcached 38 Stopwatch databaseWatch = new Stopwatch(); 39 databaseWatch.Start(); 40 SqlConnection con = OpenConnection(); 41 string cmdsql = string.Format("select * from tb_emailInfo where email='{0}' and classCode='{1}' ", user.User, user.Pass); 42 using (SqlCommand cmd = new SqlCommand(cmdsql, con)) 43 { 44 DataTable tb = new DataTable(); 45 SqlDataAdapter sda = new SqlDataAdapter(cmd); 46 sda.Fill(tb); 47 Debug.WriteLine("登陸成功!已從數據庫中取得用戶信息!已查詢到人數:" + tb.Rows.Count); 48 if (tb.Rows.Count > 0) 49 { 50 client.Set("user", user.User, DateTime.Now.AddMinutes(30));//Set中的第三個參數是指定緩存過時時間 51 client.Set("pass", user.Pass, DateTime.Now.AddMinutes(30)); 52 } 53 } 54 databaseWatch.Stop(); 55 Debug.WriteLine("數據庫取得用戶信息耗時:" + databaseWatch.ElapsedMilliseconds + "毫秒"); 56 } 57 58 public SqlConnection OpenConnection() 59 { 60 SqlConnection conn = new SqlConnection(connectKey); 61 { 62 conn.Open(); 63 Debug.WriteLine(conn.State); 64 return conn; 65 } 66 }
下面的代碼是在控制檯調用的過程:服務器
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 6 while (true) 7 { 8 UserInfo userInfo = new UserInfo();//只存儲了用戶名和密碼屬性的實體 9 Console.WriteLine("請輸入測試用戶:"); 10 userInfo.User = Console.ReadLine(); 11 Console.WriteLine("請輸入測試密碼:"); 12 userInfo.Pass = Console.ReadLine(); 13 14 SQLDataOperator sqlDO = new SQLDataOperator(); 15 Stopwatch watch = new Stopwatch(); 16 watch.Start(); 17 sqlDO.GetUserInfo(userInfo); 18 watch.Stop(); 19 20 } 21 } 22 }
最後的運行結果截圖以下:分佈式
圖一memcached
圖二性能
圖三
圖四
本文的實例是將用戶信息以字符串的形式緩存起來並提供檢索,其實也能夠直接把UserInfo實體對象緩存到Memcached中,取出來後進行轉化便可,前提是Userinfo須要有序列化關鍵字serializable關鍵字。後面有時間在更新下Memcached緩存實體的實例。
參考資料:
http://www.runoob.com/memcached/memcached-tutorial.html Memcached詳細教程
https://blog.phpha.com/backup/archives/1303.html Memcached分佈式部署
做者:悠揚的牧笛
博客地址:http://www.cnblogs.com/xhb-bky-blog/p/5782444.html
聲明:本博客原創文字只表明本人工做中在某一時間內總結的觀點或結論,與本人所在單位沒有直接利益關係。非商業,未受權貼子請以現狀保留,轉載時必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。