参考资料:C#实现Memcached分布式缓存,指定服务器保存变量
Key 的选择:
Memcaced 就相当于一个大键值对,不同系统放到Memcached 中的数据都是不隔离的,
因此设定Key 的时候要选择好Key,这样就不容易冲突。建议规则“系统名字_模块名字_业
务Key”,比如“CMS_Admin_AdminName”
Memcache封装一
在项目中安装Memcached 的.Net 开发包:Install-Package EnyimMemcached
public sealed class MemcacheHelper
{
private static MemcachedClient MemClient;
static readonly object padlock = new object();
//线程安全的单例模式
static MemcacheHelper()
{
if (MemClient == null)
{
lock (padlock)
{
if (MemClient == null)
{
MemClientInit();
}
}
}
}
private static void MemClientInit()
{
//初始化缓存()
MemcachedClientConfiguration memConfig = new MemcachedClientConfiguration();
//IPAddress newaddress = IPAddress.Parse(Dns.GetHostEntry("127.0.0.1").AddressList[0].ToString());//"127.0.0.1"替换为内网地址
//IPEndPoint ipEndPoint = new IPEndPoint(newaddress, 11211);
// 配置文件 - ip
//memConfig.Servers.Add(ipEndPoint);
//这个数组为服务器ip(做集群用的),一般都是配置在数据库或者XML中的,这里写死在这里
string[] servers = new string[] { "192.168.31.126" };//配置集群
foreach (var server in servers)
{
//配置文件 - ip
memConfig.Servers.Add(new IPEndPoint(IPAddress.Parse(server), 11211));
}
//Ketama是一种一致性哈希算法,常用于负载均衡
//当我们有多Memcached服务器的时候,使用Ketama这种Hash算法来确定数据存储到哪台服务器中
//打开memConfig.NodeLocatorFactory = new KetamaNodeLocatorFactory();这段代码后客户端
//会根据自己的算法决定把数据写入哪个Memcached服务器,取数据库的时候再根据同样的定位算法去哪台服务器上去取。
//它会自动给我们做类似负载均衡的功能(有多台Memcached服务器的时候才打开)
//memConfig.NodeLocatorFactory = new KetamaNodeLocatorFactory();
// 配置文件 - 协议 (保存数据采用二进制的形式序列化)
memConfig.Protocol = MemcachedProtocol.Binary;
// 配置文件-权限
//(一般情况下我们的Memcached都是部署在内网的,如果你要把一个Memcached部署到公网则需要做安全验证了)
//memConfig.Authentication.Type = typeof(PlainTextAuthenticator);
//memConfig.Authentication.Parameters["zone"] = "";
//memConfig.Authentication.Parameters["userName"] = "username";
//memConfig.Authentication.Parameters["password"] = "password";
//下面请根据实例的最大连接数进行设置
memConfig.SocketPool.MinPoolSize = 5;
memConfig.SocketPool.MaxPoolSize = 200;
MemClient = new MemcachedClient(memConfig);
}
/// <summary>
/// 写入缓存 【写入方式:Set】
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
public static bool Set(string key, object value)
{
if (!value.GetType().IsSerializable)
{
throw new ArgumentException("Value必须是可序列化的对象");
}
return MemClient.Store(StoreMode.Set, key, value);
}
/// <summary>
/// 写入缓存 【写入方式:Set】
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="expires">过期时间</param>
public static bool Set(string key, object value, TimeSpan expires)
{
if (!value.GetType().IsSerializable)
{
throw new ArgumentException("Value必须是可序列化的对象");
}
return MemClient.Store(StoreMode.Set, key, value, expires);
}
/// <summary>
/// 写入缓存
/// </summary>
/// <param name="method">写入方式
/// set:存在则覆盖,不存在则新增
/// Replace:如果存在则覆盖,并且返回true;如果不存在则不处理,并且返回false;
/// Add:如果不存在则新增,并且返回true;如果存在则不处理,并且返回false;
/// </param>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="expires">过期时间</param>
public static bool Set(StoreMode method, string key, object value)
{
if (!value.GetType().IsSerializable)
{
throw new ArgumentException("Value必须是可序列化的对象");
}
return MemClient.Store(method, key, value);
}
/// <summary>
/// 写入缓存
/// </summary>
/// <param name="method">写入方式
/// set:存在则覆盖,不存在则新增
/// Replace:如果存在则覆盖,并且返回true;如果不存在则不处理,并且返回false;
/// Add:如果不存在则新增,并且返回true;如果存在则不处理,并且返回false;
/// </param>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="expires">过期时间</param>
public static bool Set(StoreMode method, string key, object value, TimeSpan expires)
{
if (!value.GetType().IsSerializable)
{
throw new ArgumentException("Value必须是可序列化的对象");
}
return MemClient.Store(method, key, value, expires);
}
/// <summary>
/// 写入缓存(返回写入成功或失败的详细信息)
/// </summary>
/// <param name="method">写入方式
/// set:存在则覆盖,不存在则新增
/// Replace:如果存在则覆盖,并且返回true;如果不存在则不处理,并且返回false;
/// Add:如果不存在则新增,并且返回true;如果存在则不处理,并且返回false;
/// </param>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="expires">过期时间</param>
/// <returns>返回写入成功或失败的详细信息</returns>
public static IStoreOperationResult ExecuteSet(StoreMode method, string key, object value, TimeSpan expires)
{
if (!value.GetType().IsSerializable)
{
throw new ArgumentException("Value必须是可序列化的对象");
}
return MemClient.ExecuteStore(method, key, value, expires);
}
/// <summary>
/// 读取缓存
/// </summary>
/// <param name="key"></param>
public static T Get<T>(string key)
{
return MemClient.Get<T>(key);
}
/// <summary>
/// 读取缓存
/// </summary>
/// <param name="key">键</param>
public static object Get(string key)
{
return MemClient.Get(key);
}
/// <summary>
/// 读取缓存(返回读取成功或失败的详细信息)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns>返回读取成功或失败的详细信息</returns>
public static IGetOperationResult<T> ExecuteGet<T>(string key)
{
return MemClient.ExecuteGet<T>(key);
}
/// <summary>
/// 删除缓存[如果键不存在,则返回false]
/// </summary>
/// <param name="key">键</param>
/// <returns>true:删除成功 false:删除失败</returns>
public static bool Remove(string key)
{
return MemClient.Remove(key);
}
/// <summary>
/// 删除缓存(返回删除成功或失败的详细信息)
/// </summary>
/// <param name="key">键</param>
/// <returns>返回删除成功或失败的详细信息</returns>
public static IRemoveOperationResult ExecuteRemove(string key)
{
return MemClient.ExecuteRemove(key);
}
}
调用:
class Program
{
static void Main(string[] args)
{
MemcacheHelper.Set("NickName", "李云山", TimeSpan.FromSeconds(10)); //写入
var nick = MemcacheHelper.Get<string>("NickName"); //读取
}
}
Memcache封装二
using Enyim.Caching;
using Enyim.Caching.Configuration;
using Enyim.Caching.Memcached;
using System;
using System.Net;
namespace WebApp
{
/// <summary>
/// Memcache封装
/// </summary>
public class MemcacheMgr
{
private static MemcachedClient client;
public static MemcacheMgr Instance { get; private set; } = new MemcacheMgr();
private MemcacheMgr()
{
//这个数组为服务器ip,一般都是配置在数据库或者XML中的,这里写死在这里
string[] servers = new string[] { "127.0.0.1", "192.168.1.120", "192.168.1.121" };
MemcachedClientConfiguration config = new MemcachedClientConfiguration();
foreach (var server in servers)
{
config.Servers.Add(new IPEndPoint(IPAddress.Parse(server), 11211));
}
config.Protocol = MemcachedProtocol.Binary; //采用二进制的形式序列化
client = new MemcachedClient(config);
Instance = this;
}
/// <summary>
/// 写入缓存
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="expires">过期时间</param>
public void SetValue(string key, object value, TimeSpan expires)
{
if (!value.GetType().IsSerializable)
{
throw new ArgumentException("Value必须是可序列化的对象");
}
client.Store(StoreMode.Set, key, value, expires);
}
/// <summary>
/// 读取缓存
/// </summary>
/// <param name="key"></param>
public T GetValue<T>(string key)
{
return client.Get<T>(key);
}
}
}
调用
public ActionResult Index()
{
Person p1 = new Person() { Id = 1, Name = "张三" };
//将数据存入Memcache缓存
MemcacheMgr.Instance.SetValue("personkey", p1, TimeSpan.FromMinutes(1));
//从Memcache缓存中读取数据
var pers = MemcacheMgr.Instance.GetValue<Person>("personkey");
return View();
}