|
最近有个项目, 使用Ibatis.net需要部署在负载均衡的环境下, 显然Ibatis.net的内置缓存方式, 是不能适用的.
多个Web服务器之间的缓存不能进行同步是问题的关键. 于是决定扩展他的缓存策略, 使用MemCached.
Ibatis.net现有的缓存方式有: MEMORY, LRU, FIFO, 我们扩展一个叫MemCached的方式.
1. 实现一个ICacheController类, 先要下载一个MemCaced的客户端,
我使用的是enyim.com memcached 1.2.0.2的客户端.
/// <summary>
/// 使用MemCached做分布式缓存
/// </summary>
public class MemCachedController : ICacheController
{
MemcachedClient _mc = null;
private int _cacheSize = 0;
private IList _keyList = null;
/// <summary>
///
/// </summary>
public MemCachedController()
{
_mc = new MemcachedClient();
_cacheSize = 100;
_keyList = ArrayList.Synchronized(new ArrayList());
}
#region ICacheController Members
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public object this[object key]
{
get
{
_keyList.Remove(key);
_keyList.Add(key);
return _mc.Get(key.ToString());
}
set
{
_mc.Store(StoreMode.Set, key.ToString(), value);
_keyList.Add(key);
if (_keyList.Count > _cacheSize)
{
object oldestKey = _keyList[0];
_keyList.Remove(0);
_mc.Remove(oldestKey.ToString());
}
}
}
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public object Remove(object key)
{
//object o = _mc.Get(key.ToString());
_keyList.Remove(key);
_mc.Remove(key.ToString());
return null;
}
/// <summary>
///
/// </summary>
public void Flush()
{
//_mc.FlushAll();
foreach (object arr in _keyList)
{
_mc.Remove(arr.ToString());
}
_keyList.Clear();
}
/// <summary>
///
/// </summary>
/// <param name="properties"></param>
public void Configure(System.Collections.IDictionary properties)
{
string size = (string)properties["CacheSize"];
if (size != null)
{
_cacheSize = Convert.ToInt32(size);
}
}
#endregion
}
如上, 比较简单.
2. 第二步在DomSqlMapBuilder类中注册我们的新缓存类型.
// xionglx添加的使用MemCached
cacheAlias = new TypeAlias(typeof(MemCachedController));
cacheAlias.Name = "MEMCACHED";
_configScope.SqlMapper.TypeHandlerFactory.AddTypeAlias(cacheAlias.Name, cacheAlias);
3. 在SqlMap.xsd配置文件中注册新的类型,
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="LRU"/>
<xs:enumeration value="MEMORY"/>
<xs:enumeration value="FIFO"/>
<xs:enumeration value="MEMCACHED"/>
</xs:restriction>
</xs:simpleType>
4. Web.Config中添加配置.
<!--memcached-->
<sectionGroup name="enyim.com">
<section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching" />
</sectionGroup>
<enyim.com>
<memcached>
<servers>
<add address="127.0.0.1" port="11211" />
<!--<add address="127.0.0.1" port="20004" />-->
</servers>
<socketPool minPoolSize="10" maxPoolSize="100" connectionTimeout="00:10:00" deadTimeout="00:02:00" />
</memcached>
</enyim.com>
经过测试, 可以正常的访问MemeCached服务端, 并且缓存正常.
需要注意的是, 实体类需要标记为可序列化. 在Map文件的缓存策略中,
<cacheModels>
<cacheModel id="ModuleCache" implementation="MEMCACHED" readOnly="false">
<flushInterval hours="24"/>
<flushOnExecute statement="Module.Insert"/>
<flushOnExecute statement="Module.Update"/>
<flushOnExecute statement="Module.Delete"/>
<property name="CacheSize" value="100"/>
</cacheModel>
</cacheModels>
不能使用serialize="true", 反序列化的时候会出错, 我还没仔细查原因. 这里readOnly="false"是说, 这个对象是
会发生更改的, 只有那些系统初始化后, 不会发生变化的数据,才设置成readOnly="true". |
|
|