一、Memcached是什麼? Memcached是一個高性能的分散式記憶體對象緩存系統,可以在記憶體中緩存數據和對象來減少讀取資料庫的次數,從而提醒性能。Memcached基於一個K/V對的hashmap。 二、Memcached的特征 1. 協議簡單:基於文本協議和二進位協議進行通信 2. 基於li ...
一、Memcached是什麼?
Memcached是一個高性能的分散式記憶體對象緩存系統,可以在記憶體中緩存數據和對象來減少讀取資料庫的次數,從而提醒性能。Memcached基於一個K/V對的hashmap。
二、Memcached的特征
1. 協議簡單:基於文本協議和二進位協議進行通信
2. 基於libevent的事件處理
3. 內置記憶體存儲方式
數據存儲在記憶體中,重啟服務或系統後數據會全部消失
當記憶體容量達到指定值後,基於LRU(Least Recently Used)演算法自動刪除不適用的緩存。
4. memcached不互相通信的分散式
服務端沒有分散式供能,取決於客戶端的實現。
三、Memcached安裝
安裝命令:
sc create "Memcached Server1" start= auto binPath= "D:\Tools\memcached\memcached.exe -d runservice -m 32 -p 11220 -l 127.0.0.1" DisplayName= "Memcached Server1"
PS:修改下服務名字及埠號,就可以在一臺電腦上配置多個服務了。
啟動命令:
sc start "Memcached Server1"
卸載命令:
sc delete "Memcached Server1"
參數詳解:
-d選項是啟動一個守護進程,
-m是分配給Memcache使用的記憶體數量,單位是MB,我這裡是10MB,
-u是運行Memcache的用戶,我這裡是root,
-l是監聽的伺服器IP地址,如果有多個地址的話,我這裡指定了伺服器的IP地址192.168.0.200,
-p是設置Memcache監聽的埠,我這裡設置了12000,最好是1024以上的埠,
-c選項是最大運行的併發連接數,預設是1024,我這裡設置了256,按照你伺服器的負載量來設定,
-P是設置保存Memcache的pid文件,我這裡是保存在 /tmp/memcached.pid,
四、Memcached記憶體存儲機制:Slab Allocation
Slab Allocator的基本原理是按照預先規定的大小,將分配的記憶體分割成特定長度的塊, 以完全解決記憶體碎片問題。
Slab術語:
Page: 分配給Slab的記憶體空間,預設是1MB。分配給Slab之後根據slab的大小切分成chunk。
Chunk: 用於緩存記錄的記憶體空間
Slab Class: 特定大小的chunk的組。
memcached根據收到的數據的大小,選擇最適合數據大小的slab(圖2)。 memcached中保存著slab內空閑chunk的列表,根據該列表選擇chunk, 然後將數據緩存於其中
接下來,我們看一下具體的例子應用,看看chunk是怎麼分配的?
var str = "我是中國人"; for (var i = 0; i < 100; i++) { var temp = str; for (int j = 0; j < i; j++) { temp += str; } client.Store(StoreMode.Set, "k" + i, temp); } Console.WriteLine("chunk_size\tchunks_per_page\tchunk_key_num"); foreach (var item in GetSlabsItemList()) { Console.WriteLine("{0}\t\t{1}\t\t{2}",item.chunk_size, item.chunks_per_page, item.items_number); } Console.ReadKey();生成了100個K/V對,每一對數據量都會遞增,我們看看結果怎麼樣,如圖:
chunk_size表示chunk塊的大小,也可以看出目前所有的chunk塊的總數。
chunk_key_num表示當前chunk包含了多少個key。
結合上圖應該更好理解了。
五、實戰Memcached
本次實戰使用Enyim作為客戶端,具體配置如下。
app.config: <?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <sectionGroup name="enyim.com"> <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching" /> </sectionGroup> </configSections> <enyim.com> <memcached protocol="Binary"> <servers> <add address="127.0.0.1" port="11220" /> <add address="127.0.0.1" port="11221" /> <add address="127.0.0.1" port="11222" /> </servers> </memcached> </enyim.com> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> </startup> </configuration> 實現代碼: class Program { private static MemcachedClient client = new MemcachedClient("enyim.com/memcached"); static void Main(string[] args) { var max = 10000; for (var i = 0; i < max; i++) { client.Store(StoreMode.Set, "k" + i, "v" + i); } for (var i = 0; i < max; i++) { Console.WriteLine(client.Get("k" + i)); } ServerStats ss = client.Stats(); foreach (var endpoint in ss.GetRaw("All")) { Console.WriteLine("endpoint: {0}", endpoint.Key); IPEndPoint ipendpoint = new IPEndPoint(endpoint.Key.Address, endpoint.Key.Port); Console.WriteLine("\t\tStatItem.ItemCount:{0}", ss.GetRaw(ipendpoint, StatItem.ItemCount)); Console.WriteLine("\t\tStatItem.UsedBytes:{0}", ss.GetRaw(ipendpoint, StatItem.UsedBytes)); Console.WriteLine("\t\tStatItem.MaxBytes:{0}", ss.GetRaw(ipendpoint, StatItem.MaxBytes)); } Console.ReadKey(); } }
從代碼中,可以看出,我採用了多個服務的方式,然後我插入了10000個K/V對,Enyim客戶端會根據演算法將數據劃分到不同的memcached服務中,結果如下。
分散式演算法參考:http://xiexiejiao.cn/java/memcached-consistent-hashing.html
參考資料:
http://kb.cnblogs.com/page/42731/
http://kb.cnblogs.com/page/42732/
http://kb.cnblogs.com/page/42733/
http://kb.cnblogs.com/page/42734/
http://xiexiejiao.cn/java/memcached-consistent-hashing.html