是一緩存,能夠Set, Get value,哈哈,普通用法如下:
public User GetUser(int userId) { UserInfo user = cacheService.Get("UserInfo:" + userId) as UserInfo;//cacheService是自定義的接口,具體的memcache實現代碼被隔離了 if (user == null) { user = dao.GetUser(userId); cacheService.Set("UserInfo:" + userId, user); } return user; }
在真正使用Memcached之前,需要先初始化它,如下:
string[] serverlist = { "192.168.1.11:11211", "192.168.1.12:11211", "192.168.1.13:11211" };//服務器可以是多個 //初始化池 SockIOPool pool = SockIOPool.GetInstance(); pool.SetServers(serverlist);//設置連接池可用的cache服務器列表,server的構成形式是IP:PORT(如:127.0.0.1:11211) pool.InitConnections = 3;//初始連接數 pool.MinConnections = 3;//最小連接數 pool.MaxConnections = 5;//最大連接數 pool.SocketConnectTimeout = 1000;//設置連接的套接字超時 pool.SocketTimeout = 3000;//設置套接字超時讀取 pool.MaintenanceSleep = 30;//設置維護線程運行的睡眠時間。如果設置為0,那麼維護線程將不會啟動,30就是每隔30秒醒來一次 //獲取或設置池的故障標志。 //如果這個標志被設置為true則socket連接失敗,將試圖從另一台服務器返回一個套接字如果存在的話。 //如果設置為false,則得到一個套接字如果存在的話。否則返回NULL,如果它無法連接到請求的服務器。 pool.Failover = true; pool.Nagle = false;//如果為false,對所有創建的套接字關閉Nagle的算法 pool.Initialize();
MemcachedProvider代碼:
public class MemcachedProvider : ICache { private MemcachedClient mc = new MemcachedClient(); public void Set(string key, object o) { mc.Set(key, o); } public object Get(string key) { return mc.Get(key); } }
用法很簡單,下面說說它的一些限制:
每個key最多<=250長度
每個value最大<=1M(如果超過1M,則在C#端自己分解搞定)
沒有冗余機制,既:當某一台memcached服務器down掉後,數據就丟失了,不會自動平衡數據
示例的UML圖:
緩存的數據是通過hash後來分布到各台Memcache Server的,因此,假設每台Memcached Server都分別分配到4G內存的話,那我們的C#程序就能夠用到12G內存。這個說法其實不准確,能否用足這12G的內存,完全看MemcacheClient端的分布key的算法(上圖中左邊接口部分),等以後再深入研究這個算法。
下面來說說當某台memcached server down掉後的解決辦法(共3種解決方法):
用熱備節點
從配置文件裡去掉那台失效的memcached server的ip
增加一台Backup Memcached Server
一、用熱備節點
程序端不改變任何東西
當發現某memcached server down機後,啟動一台新memcached server,並且把新memcached server的IP修改為down機的IP(down掉的那台不要拿單獨修復)
這個辦法不利的地方是:在down掉和上線期間,緩存是沒有的,會throw exception,需要程序捕獲,並且當成null值來處理,會增加數據庫的壓力
二、從配置文件裡去掉那台失效的memcached server的ip
那就是修改配置文件了,然後再把down掉的server慢慢修復,等修復後再修改配置文件...
非常不好,光修改配置文件就要導致application reset了。不過當資源有限時,也只能這樣了。
查看本欄目
三、增加一台Backup Memcached Server
物理節點圖如下:
C#端:由原先的一個MemcachedClient客戶端變成了"MemcachedClient"和"BackupMemcachedClient"共同存在
Memcached server服務器端:增加一台Backup Memcached Server,這台server性能和內存都要高於其他三台memcached server的配置,這台server將保存所有的cache,因此性能要求高,尤其是網絡和內存。
先初始化這2個pool:
string[] serverlist = { "192.168.1.11:11211", "192.168.1.12:11211", "192.168.1.13:11211" };//普通Memcached服務器 //初始化池 SockIOPool pool = SockIOPool.GetInstance("NormalServers"); //設置PoolName pool.SetServers(serverlist);//設置連接池可用的cache服務器列表,server的構成形式是IP:PORT(如:127.0.0.1:11211) pool.InitConnections = 3;//初始連接數 pool.MinConnections = 3;//最小連接數 pool.MaxConnections = 5;//最大連接數 pool.SocketConnectTimeout = 1000;//設置連接的套接字超時 pool.SocketTimeout = 3000;//設置套接字超時讀取 pool.MaintenanceSleep = 30;//設置維護線程運行的睡眠時間。如果設置為0,那麼維護線程將不會啟動,30就是每隔30秒醒來一次 //獲取或設置池的故障標志。 //如果這個標志被設置為true則socket連接失敗,將試圖從另一台服務器返回一個套接字如果存在的話。 //如果設置為false,則得到一個套接字如果存在的話。否則返回NULL,如果它無法連接到請求的服務器。 pool.Failover = true; pool.Nagle = false;//如果為false,對所有創建的套接字關閉Nagle的算法 pool.Initialize(); string[] backupServerlist = { "192.168.1.14:11211"}; //Backup服務器 //初始化池 SockIOPool backupPool = SockIOPool.GetInstance("BackupServers"); //設置PoolName backupPool.SetServers(backupServerlist);//設置連接池可用的cache服務器列表,server的構成形式是IP:PORT(如:127.0.0.1:11211) backupPool.InitConnections = 3;//初始連接數 backupPool.MinConnections = 3;//最小連接數 backupPool.MaxConnections = 5;//最大連接數 backupPool.SocketConnectTimeout = 1000;//設置連接的套接字超時 backupPool.SocketTimeout = 3000;//設置套接字超時讀取 backupPool.MaintenanceSleep = 30;//設置維護線程運行的睡眠時間。如果設置為0,那麼維護線程將不會啟動,30就是每隔30秒醒來一次 //獲取或設置池的故障標志。 //如果這個標志被設置為true則socket連接失敗,將試圖從另一台服務器返回一個套接字如果存在的話。 //如果設置為false,則得到一個套接字如果存在的話。否則返回NULL,如果它無法連接到請求的服務器。 backupPool.Failover = true; backupPool.Nagle = false;//如果為false,對所有創建的套接字關閉Nagle的算法 backupPool.Initialize();
MemcachedProvider改為:
public class MemcachedProvider : ICache { private static MemcachedClient GetNormalServerClient() { MemcachedClient mc = new MemcachedClient(); mc.PoolName = "NormalServers"; return mc; } private static MemcachedClient GetBackupServerClient() { MemcachedClient mc = new MemcachedClient(); mc.PoolName = "BackupServers"; return mc; } public void Set(string key, object o) { try { GetNormalServerClient().Set(key, o); GetBackupServerClient().Set(key, o); //這個看情況改為異步執行 } catch { //notify or log } } public object Get(string key) { object o=null; try { o = GetNormalServerClient().Get(key); } catch { //notify or log } if (o != null) return o; try { o = GetBackupServerClient().Get(key); } catch { //notify or log } return o; } }
就這些吧。
作者:cnblogs Aaron