分布式缓存之Memcache
〇、為什么要用分布式緩存
? 1.軟件從單機到分布式
走向分布式第一步就是解決:多臺機器共享登錄信息的問題。
例如:現在有三臺機器組成了一個Web的應用集群,其中一臺機器用戶登錄,然后其他另外兩臺機器共享登錄狀態?
解決1:AspNet 進程外的Session。
解決2:用數據庫存儲當前登錄狀態。
解決3:Memcache 【性能最好,類似的:Redis,NoSql】
? 2.Memcache基本原理
Socket 服務器端
數據:鍵值對存儲
內存處理的算法:
本質就是一個大的哈希表。key最大長度是255個字符。
內存模型:Memcache預先將可支配的內存空間進行分區(Slab),每個分區里再分成多個塊(Chunk)最大1MB,但同一個分區里:塊的長度(bytes)是固定的。
插入數據:查找適合自己長度的塊,然后插入,會有內存浪費。
LRU,閑置>過期 >最少訪問
惰性刪除:它并沒有提供監控數據過期的機制,而是惰性的,當查詢到某個key數據時,如果過期那么直接拋棄。
集群搭建原理:
Memcache服務器端并沒有提供集群功能,但是通過客戶端的驅動程序實現了集群配置。
客戶端實現集群的原理:首先客戶端配置多臺集群機器的ip和端口的列表。然后客戶端驅動程序在寫入之前,首先對key做哈希處理得到哈希值后對總的機器的個數進行取余然后就選擇余數對應的機器。
3.
key最大250個字符,item最大1MB,當然key/item最好都別太大,最長過期時間是30天
Memcache預先將可支配的內存空間進行分區(Slab),每個分區里再分成多個塊(Chunk),但同一個分區里:塊的長度(bytes)是固定的。
將記錄從Memcache刪除后,已經分配的內存(即Chunk),也不會被釋放,而是會重復利用,這樣就徹底解決了內存碎片的問題
Memcache采用“惰性”方式來應對記錄的超期問題
一致性哈希處理: http://www.cnblogs.com/lanceyan/archive/2013/05/13/3075044.html
解決多線程問題:
4. CAS的基本原理
Memcached于1.2.4版本新增CAS協議,類同于Java并發包中CAS(Compare and Set)原子操作,用來處理同一item被多個線程更改過程的并發問題.
基本原理非常簡單,簡而言之就是”版本號”.每個存儲的數據對象都有一個版本號.在Memcached中,每個key關聯有一個64bit長度的long型唯一數值,表示該key對應value的版本號.
這個數值由Memcached產生,從1開始,且同一Memcached不會重復,在兩種情況下這個版本數值會加,即新增與更新,而刪除item版本值不會減小.
我們可以從下面的例子來理解:
如果不采用CAS,則有如下的情景:
第一步,A取出數據對象X;
第二步,B取出數據對象X;
第三步,B修改數據對象X,并將其放入緩存;
第四步,A修改數據對象X,并將其放入緩存。
我們可以發現,第四步中會產生數據寫入沖突。
如果采用CAS協議,則是如下的情景。
第一步,A取出數據對象X,并獲取到CAS-ID1;
第二步,B取出數據對象X,并獲取到CAS-ID2;
第三步,B修改數據對象X,在寫入緩存前,檢查CAS-ID與緩存空間中該數據的CAS-ID是否一致。結果是“一致”,就將修改后的帶有CAS-ID2的X寫入到緩存。
第四步,A修改數據對象Y,在寫入緩存前,檢查CAS-ID與緩存空間中該數據的CAS-ID是否一致。結果是“不一致”,則拒絕寫入,返回存儲失敗。
?
5.
將Memcache.exe安裝為Windows服務:Memcache.exe -d install
啟動Memcache服務:Memcache.exe -d start
啟動Memcache服務(windows命令):net start "Memcache Server"
停止Memcache服務(windows命令):net stop "Memcache Server"
連接到Memcache控制臺:telnet ServerIP 11211
打印當前Memcache服務器狀態:stats
打印當前Memcache服務器Items(記錄)的統計信息:stats items
打印當前Memcache服務器Slab(分區)及Chunk(塊)的統計信息:stats slabs
打印指定Slab中的KEY列表(可用于遍歷items,但效率較低,慎用!):stats cachedump SlabId Limit_num。顯示結果:ITEM KeyName [ValueByteLength b; LastAccessTime s]。值得注意的是,經過測試確認:那個LastAccessTime并不是記錄到期時間,而是最后一次的get時間,并且get之后,也不會自動延長expiry(到期時間)。
添加新記錄:add KeyName 0 0 ValueByteLength [回車] ValueContent
刪除記錄 : delete KeyName
添加或更新記錄 : set KeyName 0 0 ValueByteLength [回車] ValueContent
更新記錄 : replace KeyName 0 0 ValueByteLength [回車] ValueContent
?
參考:http://www.cnblogs.com/lost-1987/articles/3069460.html
http://wenku.baidu.com/view/e30db586ec3a87c24028c401.html
也可以圖形化監控 Memcached 的運行狀態
http://livebookmark.net/journal/2008/05/21/memcachephp-stats-like-apcphp/
在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\memcached Server 下面找到一個 ImagePath 的字符串項,正好是服務的執行路徑的字符串,雙擊該串,在后面加入 -l 192.168.1.135 -m 45 -p 12345 (訪問ip為:192.168.1.135 使用45M內存,12345為端口),再啟動服務。
?
6.
一、關于Memcache的介紹及Windows下的簡單使用請參考文章 ?《分布式緩存系統Memcached簡介與實踐》
二、使用Memcache場景
三、主要示例代碼
1.自定義的MemcachedHelper類
using Memcached.ClientLibrary; using System; using System.Collections.Generic; using System.Linq; using System.Web;namespace LearnMemcached.Helper {public static class MemcachedHelper{private static MemcachedClient mc;static MemcachedHelper(){// 緩存服務器IP列表String[] serverlist = { "127.0.0.1:11211" };// initialize the pool for memcache serversSockIOPool pool = SockIOPool.GetInstance("test");pool.SetServers(serverlist);pool.Initialize();mc = new MemcachedClient();mc.PoolName = "test";mc.EnableCompression = false;}public static bool Set(string key, object value,DateTime expiry){return mc.Set(key, value, expiry);}public static object Get(string key){return mc.Get(key);}public static void Delete(string key){mc.Delete(key);}} } View Code2.BaseController基類
using LearnMemcached.Helper; using LearnMemcached.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc;namespace LearnMemcached.Controllers {public class BaseController : Controller{public T_Users LoginUser { get; set; }/// <summary>/// 因為項目中所有的Controller控制器類均繼承自BaseController類,所以子控制器類的Action方法在/// 執行前都會先執行OnActionExecuting方法,該方法的主要作用就是判斷用戶是否已經登錄/// </summary>/// <param name="filterContext"></param>protected override void OnActionExecuting(ActionExecutingContext filterContext){base.OnActionExecuting(filterContext);// 獲取請求參數中的SessionIdstring sessionId = Request["SessionId"];if(string.IsNullOrEmpty(sessionId)){Response.Redirect("/Account/Index");}// 從緩存服務器中根據SessionId獲取用戶信息T_Users user = MemcachedHelper.Get(sessionId) as T_Users;if(user == null){Response.Redirect("/Account/Index");}else {LoginUser = user;ViewBag.User = LoginUser;}}} } View Code3.AccountController類
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using LearnMemcached.Models; using LearnMemcached.Helper; using LearnMemcached.Models.ViewModel;namespace LearnMemcached.Controllers {public class AccountController : Controller{// GET: Accountpublic ActionResult Index(){return View();}public ActionResult Login(LoginUser loginUser){if(!ModelState.IsValid){// 登錄失敗return Content("false");}WebPortalEntities db = new WebPortalEntities();T_Users user = db.T_Users.Where(u => u.LoginId.Equals(loginUser.LoginId) && u.Password.Equals(loginUser.Password)).SingleOrDefault();if(user == null){return Content("false");}else{// 自定義SessionId的規則string sessionId = "baidu-IT-DonNet-" + Guid.NewGuid().ToString();// 把SessionId保存到客戶端瀏覽器中,客戶端下次請求的時候會自動帶上該參數Response.Cookies["SessionId"].Value = sessionId;// 把SessionId和user對象以key-value鍵值對的形式保存在緩存服務器中MemcachedHelper.Set(sessionId, user, DateTime.Now.AddMinutes(30));return Content("true");}}[HttpPost]public ActionResult LogOff(){MemcachedHelper.Delete(Request["SessionId"]);return RedirectToAction("Index");}} } View Code?
下載示例代碼
轉載于:https://www.cnblogs.com/shaomenghao/p/4177207.html
總結
以上是生活随笔為你收集整理的分布式缓存之Memcache的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 清楚xcode缓存(老是忘记所有记下来方
- 下一篇: Maven搭建springMVC+spr