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