Lucene在索引数据比较少的时候内存问题不是很明显,但如果索引文件有几个G的时候,内存就会出现溢出问题.这个问题是由于Lucene的内部Bug引起的,如果在搜索时设置了排序,则它会缓存相关数据,但在下一次搜索时,它没有清除内部的一些缓存数据,所以会造成内存溢出.这个问题的解决办法就是改Lucene的源代码.
        修改步骤如下:
        1.修改Lucene源代码中Index目录中的IndexReader.cs文件,在其中加上如下代码:
           public string m_cacheKey = null; (这一行代码主要用于Lucene内部用缓存的键值),以后清除缓存就用这个键值.
       2.修改Lucene源代码中Search目录中的IndexSearcher.cs文件,修改其中的Close方法代码如下:
          public override void  Close()
  {
            //清除缓存数据
            if (!string.IsNullOrEmpty(reader.m_cacheKey))
            {
                if (null != FieldSortedHitQueue.Comparators)
                {
                    FieldSortedHitQueue.Comparators.ReleaseCache(reader.m_cacheKey);
                }
                Lucene.Net.Search.FieldCache_Fields.DEFAULT.ReleaseFieldCache(reader.m_cacheKey);
                Lucene.Net.Search.ExtendedFieldCache_Fields.EXT_DEFAULT.ReleaseExtendedFieldCache(reader.m_cacheKey);
                // 立即回收垃圾
                GC.Collect();
            }                   
            //关闭读取器
   if (closeReader)
    reader.Close();
  }
 
           3.修改Lucene源代码中Search目录中的FieldCache.cs文件,修改其中的接口public interface FieldCache,并添加接口方法,方法代码如下:
          //用于清除缓存
        void ReleaseFieldCache(string strCacheKey);
 
          4.修改Lucene源代码中Search目录中的FieldCacheImpl.cs文件,添加下列方法,
代码如下:
             //用于清除缓存
        public void ReleaseFieldCache(string strCacheKey)
        {
            bytesCache.ReleaseCache(strCacheKey);
            shortsCache.ReleaseCache(strCacheKey);
            intsCache.ReleaseCache(strCacheKey);
            floatsCache.ReleaseCache(strCacheKey);
            stringsCache.ReleaseCache(strCacheKey);
            stringsIndexCache.ReleaseCache(strCacheKey);
            autoCache.ReleaseCache(strCacheKey);
            customCache.ReleaseCache(strCacheKey);
        }
   
        修改内部类:internal abstract class Cache,添加方法如下:
           //用于清除缓存
            public void ReleaseCache(string strCacheKey)
            {
                if (null != readerCache)
                {
                    lock (readerCache.SyncRoot)
                    {
                        if (null != readerCache[strCacheKey])
                        {
                            ((System.Collections.Hashtable)readerCache[strCacheKey]).Clear();
                        }                       
                    }
                }
            }
 
            修改方法Get:
               public virtual System.Object Get(IndexReader reader, System.Object key)
   {
    System.Collections.IDictionary innerCache;
    System.Object value_Renamed;
    lock (readerCache.SyncRoot)
    {
                    //改键值为静态值
                    innerCache = (System.Collections.IDictionary)readerCache[reader.m_cacheKey];
     //innerCache = (System.Collections.IDictionary) readerCache[reader];
     if (innerCache == null)
     {
      innerCache = new System.Collections.Hashtable();
                         //改键值为静态值
                        readerCache[reader.m_cacheKey] = innerCache;
      //readerCache[reader] = innerCache;
      value_Renamed = null;
     }
     else
     {
      value_Renamed = innerCache[key];
     }
     if (value_Renamed == null)
     {
      value_Renamed = new CreationPlaceholder();
      innerCache[key] = value_Renamed;
     }
    }
    if (value_Renamed is CreationPlaceholder)
    {
     lock (value_Renamed)
     {
      CreationPlaceholder progress = (CreationPlaceholder) value_Renamed;
      if (progress.value_Renamed == null)
      {
       progress.value_Renamed = CreateValue(reader, key);
       lock (readerCache.SyncRoot)
       {
        innerCache[key] = progress.value_Renamed;
       }
      }
      return progress.value_Renamed;
     }
    }
    return value_Renamed;
   }
          
     5.修改Lucene源代码中Search目录中的ExtendedFieldCache.cs文件,修改其中的接口public interface ExtendedFieldCache : FieldCache,并添加接口方法,方法代码如下:
          //用于清除缓存
        void ReleaseExtendedFieldCache(string strCacheKey);
 
        6.修改Lucene源代码中Search目录中的ExtendedFieldCacheImpl.cs文件,添加下列方法,代码如下:
          //用于清除缓存
        public void ReleaseExtendedFieldCache(string strCacheKey)
        {
            longsCache.ReleaseCache(strCacheKey);
            doublesCache.ReleaseCache(strCacheKey);
            autoCache.ReleaseCache(strCacheKey);
        }
 
 
通过上述6个步骤,内存溢出问题就可以解决了,但还有一个需要注意的就是在更新索引时,一定要调用如下代码,才能清掉缓存:
//清缓排序缓存数据
IndexSearcher.Close();
IndexReader.Close();
 
 
 
 
深圳E搜科技(搜索引擎技术钻研者!)
QQ群:15911745
QQ:448114915;934724029
Mobile:13168078506;13713628016
Email:[email protected];[email protected]