您的位置:首页 > 数据库 > Memcache

IBatis.Net使用MemCached替换内置缓存策略

2009-11-24 10:13 369 查看
最近有个项目, 使用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".
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: