基类里初始化一个MemcachedClient示例Client,这个Client的方法里封装了较多的函数。查看源码可以知道,它们本质上都是向Memcached服务端发送相关指令(run command),然后解析返回的二进制数据,如果您熟悉memcached所使用的协议,理解起来应该会相当简单。本文示例只使用了客户端提供的几个方法。
同时要注意,在实现具体缓存服务的时候,CacheWriterService有两个构造函数,其中带参数的是为缓存显式指定过期时间。这个参数在实际应用中通常需要配置,显然是比较灵活一些的。
![]()
//writer 使用memcached默认过期时间
ICacheReaderService reader = CacheBuilder.GetReaderService();
//reader
#region 字符串
string strKey = "
hello";
bool isOK = writer.Remove(strKey);
//移除
Console.WriteLine("
Removed key {0}:{1}", strKey, isOK);
writer.Add(strKey, "
hello world");
//添加
Console.WriteLine("
Add key {0}, value:hello world", strKey);
bool isExists = reader.isExists(strKey);
//是否存在
Console.WriteLine("
Key {0} exists:{1}", strKey, isExists);
string result = reader.Get(strKey)
as string;
//查询
Console.WriteLine("
Get key {0}:{1}", strKey, result);
bool isModify = writer.Modify(strKey, "
Hello Memcached!");
//修改
Console.WriteLine("
Modify key {0}, value:Hello Memcached. The result is:{1}", strKey, isModify);
result = reader.Get<
string>(strKey);
Console.WriteLine("
Generic get key {0}:{1}", strKey, result);
isOK = writer.Remove(strKey);
Console.WriteLine("
Removed key {0}:{1}", strKey, isOK);
isExists = reader.isExists(strKey);
Console.WriteLine("
Key {0} exists:{1}", strKey, isExists);
result = reader.Get(strKey)
as string;
Console.WriteLine("
Get key {0}:{1}", strKey, result);
result = reader.Get<
string>(strKey);
Console.WriteLine("
Generic get key {0}:{1}", strKey, result);
Console.WriteLine();
Console.WriteLine("
===========================================");
Console.Read();
#endregion
#region 时间
DateTime dtNow = DateTime.Now;
strKey = "
datetime";
isOK = writer.Remove(strKey);
//移除
Console.WriteLine("
Removed key {0}:{1}", strKey, isOK);
writer.Add(strKey, dtNow);
//添加
Console.WriteLine("
Add key {0}, value:{1}", strKey, dtNow);
isExists = reader.isExists(strKey);
//是否存在
Console.WriteLine("
Key {0} exists:{1}", strKey, isExists);
DateTime dt = (DateTime)reader.Get(strKey);
//查询
Console.WriteLine("
Get key {0}:{1}", strKey, dt);
dt = reader.Get<DateTime>(strKey);
Console.WriteLine("
Generic get key {0}:{1}", strKey, dt);
isOK = writer.Remove(strKey);
Console.WriteLine("
Removed key {0}:{1}", strKey, isOK);
isExists = reader.isExists(strKey);
Console.WriteLine("
Key {0} exists:{1}", strKey, isExists);
Console.WriteLine("
Get key {0}:{1}", strKey, reader.Get(strKey));
Console.WriteLine("
Generic get key {0}:{1}", strKey, reader.Get<DateTime>(strKey));
//default(datetime)
Console.WriteLine();
Console.WriteLine("
===========================================");
Console.Read();
#endregion
#region 类
dtNow = DateTime.Now;
Province province =
new Province(13579, "
江苏", dtNow, dtNow);
strKey =
string.Format("
{0}_{1}", province.GetType().Name, province.Id);
//省
isOK = writer.Remove(strKey);
//移除
Console.WriteLine("
Removed key {0}:{1}", strKey, isOK);
writer.Add(strKey, province);
//添加
Console.WriteLine("
Add key {0}, value:{1}", strKey, dtNow);
isExists = reader.isExists(strKey);
//是否存在
Console.WriteLine("
Key {0} exists:{1}", strKey, isExists);
Province queryProvince = (Province)reader.Get(strKey);
//查询
Console.WriteLine("
Get key {0}:{1}", strKey, queryProvince.ProvinceName);
queryProvince = reader.Get<Province>(strKey);
Console.WriteLine("
Generic get key {0}:{1}", strKey, queryProvince.ProvinceName);
isOK = writer.Remove(strKey);
Console.WriteLine("
Removed key {0}:{1}", strKey, isOK);
isExists = reader.isExists(strKey);
Console.WriteLine("
Key {0} exists:{1}", strKey, isExists);
Console.WriteLine("
Get key {0}:{1}", strKey, reader.Get(strKey));
Console.WriteLine("
Generic get key {0}:{1}", strKey, reader.Get<Province>(strKey));
Console.WriteLine();
Console.WriteLine("
===========================================");
Console.Read();
#endregion
#region 集合(列表)
dtNow = DateTime.Now;
IList<City> listCities =
new List<City>();
City city =
new City(135, province.Id, "
南京", "
210000", dtNow, dtNow);
listCities.Add(city);
city =
new City(246, province.Id, "
苏州", "
215000", dtNow, dtNow);
listCities.Add(city);
strKey =
string.Format("
List_{0}_{1}_{2}", province.GetType().Name, province.Id, city.GetType().Name);
//省份对应城市
isOK = writer.Remove(strKey);
//移除
Console.WriteLine("
Removed key {0}:{1}", strKey, isOK);
writer.Add(strKey, listCities);
//添加
Console.WriteLine("
Add key {0}, value:", strKey);
foreach (var item
in listCities)
{
Console.WriteLine("
CityId:{0} CityName:{1}", item.Id, item.CityName);
}
isExists = reader.isExists(strKey);
//是否存在
Console.WriteLine("
Key {0} exists:{1}", strKey, isExists);
IList<City> queryCities = reader.Get(strKey)
as IList<City>;
//查询
Console.WriteLine("
Get key {0}:", strKey);
foreach (var item
in queryCities)
{
Console.WriteLine("
CityId:{0} CityName:{1}", item.Id, item.CityName);
}
queryCities = reader.Get<IList<City>>(strKey);
Console.WriteLine("
Generic get key {0}:", strKey);
foreach (var item
in queryCities)
{
Console.WriteLine("
CityId:{0} CityName:{1}", item.Id, item.CityName);
}
isOK = writer.Remove(strKey);
Console.WriteLine("
Removed key {0}:{1}", strKey, isOK);
isExists = reader.isExists(strKey);
Console.WriteLine("
Key {0} exists:{1}", strKey, isExists);
Console.WriteLine("
Get key {0}:{1}", strKey, reader.Get(strKey));
Console.WriteLine("
Generic get key {0}:{1}", strKey, reader.Get<IList<City>>(strKey));
Console.WriteLine();
Console.WriteLine("
===========================================");
Console.Read();
#endregion
#region 集合(字典)
dtNow = DateTime.Now;
IDictionary<
int, City> dictCities =
new Dictionary<
int, City>();
city =
new City(123, province.Id, "
镇江", "
212000", dtNow, dtNow);
dictCities.Add(city.Id, city);
city =
new City(321, province.Id, "
扬州", "
225000", dtNow, dtNow);
dictCities.Add(city.Id, city);
strKey =
string.Format("
Dictionary_{0}_{1}_{2}", province.GetType().Name, province.Id, city.GetType().Name);
//省份对应城市
isOK = writer.Remove(strKey);
//移除
Console.WriteLine("
Removed key {0}:{1}", strKey, isOK);
writer.Add(strKey, dictCities);
//添加
Console.WriteLine("
Add key {0}, value:", strKey);
foreach (var item
in dictCities)
{
Console.WriteLine("
CityId:{0} CityName:{1}", item.Key, item.Value.CityName);
}
isExists = reader.isExists(strKey);
//是否存在
Console.WriteLine("
Key {0} exists:{1}", strKey, isExists);
IDictionary<
int, City> queryDictCities = reader.Get(strKey)
as IDictionary<
int, City>;
//查询
Console.WriteLine("
Get key {0}:", strKey);
foreach (var item
in queryDictCities)
{
Console.WriteLine("
CityId:{0} CityName:{1}", item.Key, item.Value.CityName);
}
queryDictCities = reader.Get<IDictionary<
int, City>>(strKey);
Console.WriteLine("
Generic get key {0}:", strKey);
foreach (var item
in queryDictCities)
{
Console.WriteLine("
CityId:{0} CityName:{1}", item.Key, item.Value.CityName);
}
isOK = writer.Remove(strKey);
Console.WriteLine("
Removed key {0}:{1}", strKey, isOK);
isExists = reader.isExists(strKey);
Console.WriteLine("
Key {0} exists:{1}", strKey, isExists);
Console.WriteLine("
Get key {0}:{1}", strKey, reader.Get(strKey));
Console.WriteLine("
Generic get key {0}:{1}", strKey, reader.Get<IDictionary<
int, City>>(strKey));
Console.WriteLine();
Console.WriteLine("
===========================================");
Console.Read();
#endregion
在我的简单测试中,对常见基础数据类型如(字符串、数组、数字和时间)、集合(列表和字典)都有良好的表现,对datatable和dataset同样表现不俗,但是不太建议直接缓存这两种重粒度的类型。
在本地计算机上进行10万次循环添加缓存的过程中,发现系统内存果然增加的非常厉害。然后查询性能并没有显著下降,也许和我的单机测试环境有关,所以我认为测试结果并没有说服力,要知道,memcached的优势是它的分布式缓存实现。
有人发现如何保证缓存系统的键唯一也非常令人头疼。同样的缓存框架,不同项目不同开发者如何保证自己程序添加的缓存键唯一呢?有一种简单方法就是通过拼接字符串成为有意义的主键,比如按照项目名、命名空间、类名、数据库中的主键组合构成主键等等。当然了,在查询的时候也要自己封装特定格式的字符串主键。个人感觉确实是一个行之有效的方法。