【實踐】Memcached實例解析

關於Memcached

Memcached是一個自由開源的,高性能分佈式內存對象緩存系統。 Memcached是一種基於內存的Key-Value存儲,用來存儲小塊的任意數據(字符串、對象)。這些數據能夠是數據庫調用、API調用或者是頁面渲染的結果。 Memcached簡潔而強大。它的簡潔設計便於快速開發,減輕開發難度,解決了大數據量緩存的不少問題。它的API兼容大部分流行的開發語言。 本質上,它是一個簡潔的key-value存儲系統。 通常的使用目的,是經過緩存數據庫查詢結果,減小數據庫訪問次數,以提升動態Web應用的速度、提升可擴展性。php

 

Memcached特徵

Memcached做爲高速運行的分佈式緩存服務器,具備如下的特色。html

  • 協議簡單
  • 基於libevent的事件處理
  • 內置內存存儲方式
  • Memcached不互相通訊的分佈式

Memcached的分佈式部署極其簡單,一般較小的應用一臺Memcached服務器就能夠知足需求,可是大中型項目可能就須要多臺Memcached服務器了,這就牽涉到一個分佈式部署的問題。對於多臺Memcached服務器,怎麼肯定一個數據應該保存到哪臺服務器呢?有兩種方案,一是普通Hash分佈,二是一致性Hash分佈。普通Hash分佈對於Memcached服務器數量固定的狀況推薦使用,比較簡單。可是當服務器數量發生改變時,問題就出來了。由於同一個KEY經Hash算法處理後,與服務器數量取模,會致使結果與服務器數量未變化時不一樣,這就致使以前保存的數據丟失。採起一致性Hash分佈能夠有效的解決這個問題,把丟失的數據減到最小(注意這裏並無說徹底不丟失)。算法

Memcached實際運用

下面經過一個簡單的實例來講明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

 聲明:本博客原創文字只表明本人工做中在某一時間內總結的觀點或結論,與本人所在單位沒有直接利益關係。非商業,未受權貼子請以現狀保留,轉載時必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。

相關文章
相關標籤/搜索