最近接手一个公司的论坛。主题数量大概有100W,回复数有900W,在线人数3000左右。之前设计论坛的GG采用静态集合来缓存每个版块的主题列表。但论坛偶尔会冒出个缓存的bug,其中解决了些问题,但时不时又会有新的bug。ms有点“野火烧不尽春风吹又生”的感觉... 所以我也想着手改善一下,想了想决定重写个原型出来,暂放cnblogs希望大虾们能指点一下迷津。

      最近接手一个公司的论坛。主题数量大概有100W,回复数有900W,在线人数3000左右。之前设计论坛的GG采用静态集合来缓存每个版块的主题列表。但论坛偶尔会冒出个缓存的bug,其中解决了些问题,但时不时又会有新的bug。ms有点“野火烧不尽春风吹又生”的感觉...
所以我也想着手改善一下,想了想决定重写个原型出来,暂放cnblogs希望大虾们能指点一下迷津。

      我之前的想法是论坛启动时往Memcached服务器填上大量数据,然后Web服务器直接找Cache服务器增、删、改、查 操作。再调个Task跑作业来更新数据库。但因为种种原因再加种种其它原因。所以没有用上Memcached。所以只能凑合利用上Web服务器的内存来改善一下数据库的紧张请求。
现在没有Cache服务器,就用Web服务器的内存吧。目前大体思路是这样:

[1]论坛初始化,获取所有版块ID,循环为每个版块装载一定数量的主题到静态的DictionaryList<T>里(这个DL集合是我要实现的东西)。[2]实现一个线程池,线程池定义了一些参数,能定时定量的更新数据库。
[3]当用户发布一个新主题时,将新的主题Id和内容插入到静态DL集合的顶部,同时删除DL集合的尾部结点。同时将该主题实体插入线程池。
[4]DL集合需要实现功能如下:
   1、获取分页列表
   2、根据主题ID获取主题实体。(如果静态缓存找不到则从数据库里找)
   3、发布一个新主题时,该主题能插入到DL集合顶端。(论坛贴子都是顶上去的)
   4、DL集合需要保持一定数量数据,以根据用户操作和实际情况来修改缓存主题数量。
   5、.....未知...

DL集合实现:测试代码下载连接

using System;
using System.Collections.Generic;
using System.Text;

namespace Phantaci.Test

{

    /// <summary>

    /// 原因:

    /// List集合有根据索引查找的功能,但不支持 key,Value 形式的集合。

    /// Dictionary支持这种集合,但又不支持索引查找.所以两者关联起来一起用。

    /// 

    /// 需求:

    /// 我需要一个集合类,即能根据集合的索引段来获取实体列表,同时又要根据某个实体ID来获取这个实体。

    /// 当我往集合里"插入、"更新"、"编辑"实体时,当前操作的实体需要置于集合的顶部,同时为了保持实体总数(EntityDictionary.Count),需去除尾部实体。

    /// 

    /// 应用:

    /// 论坛版块列表缓存。当用户进入某版块时,则从DictionaryList获取一个分页列表。当"发表主题"时则把新主题置于DictionaryList顶部。

    /// 同时删除尾部最后一个节,以保持最新的固定的实体数量。主要作用是缓存版块前几十页频繁更新的列表。

    /// </summary>

    /// <typeparam name="T"></typeparam>
    public class DictionaryList<T>

    {

        /// <summary>

        /// 用于存放所有实体列表集合类 TopicId,Entity

        /// </summary>
        private Dictionary<int, T> _entityDictionary = new Dictionary<int, T>();

        //private Object _objLock = new Object(); 


        /// <summary>

        /// 索引主题集合类 用于存放TopicId 与 _entityDictionary关联

        /// </summary>
        private List<int> _indexList = new List<int>();


        private int _pageIndex;

        private int _pageSize;


        /// <summary>

        /// 当前索引

        /// </summary>
        public int PageIndex

        {

            get { return _pageIndex; }

            set { _pageIndex = value; }

        }


        /// <summary>

        /// 分页大小

        /// </summary>
        public int PageSize

        {

            get { return _pageSize; }

            set { _pageSize = value; }

        }


        /// <summary>

        /// 实体列表

        /// </summary>
        public Dictionary<int, T> EntityDictionary

        {

            get { return _entityDictionary; }

            set { _entityDictionary = value; }

        }


        /// <summary>

        /// 实体总数

        /// </summary>
        public int ItemsCount

        {

            get { return _entityDictionary.Count; }

        }


        /// <summary>

        /// 总页数

        /// </summary>
        public int PageCount

        {

            get { return (ItemsCount - 1) / PageSize + 1; }

        }


        /// <summary>

        /// 默认构造函数

        /// </summary>
        public DictionaryList()

        {

            this._pageIndex = 1;

            this._pageSize = 20;

        }


        /// <summary>

        /// 有参构造

        /// </summary>

        /// <param name="pageSize"></param>

        /// <param name="entity"></param>
        public DictionaryList(int pageSize, Dictionary<int, T> dict)

        {

            this._pageIndex = 1;

            this._pageSize = pageSize;

            this._entityDictionary = dict;


            _indexList.Clear();


            foreach (KeyValuePair<int, T> kvp in _entityDictionary)

            {

                _indexList.Add(kvp.Key);

            }

        }


        /// <summary>

        /// 清除集合列表

        /// </summary>
        public void Clear()

        {

            _indexList.Clear();

            _entityDictionary.Clear();

        }


        /// <summary>

        /// 添加一个实体

        /// 线程不安全???

        /// </summary>

        /// <param name="key"></param>

        /// <param name="entity"></param>
        public void AddItems(int key, T entity)

        {

            if (!_entityDictionary.ContainsKey(key))

            {

                //不存在则往Dictionary添加一个实体(排序问题由List<int>来关联解决)
                _entityDictionary.Add(key, entity);

                //关联List<int>
                _indexList.Insert(0, key);


                //删除列表最底部节点数据
                _indexList.RemoveAt(_indexList.Count - 1);

                _entityDictionary.Remove(_indexList[_indexList.Count - 1]);

            }

            else

            {

                //如果存在,则删除已存在的节点.同时向顶点添加该节点
                _indexList.Remove(key);

                _indexList.Insert(0, key);

            }

        }


        /// <summary>

        /// 获取一个实体

        /// </summary>

        /// <param name="key"></param>

        /// <returns></returns>
        public T GetItems(int key)

        {

            return _entityDictionary[key];

        }


        /// <summary>

        /// 是否存当前Key

        /// </summary>

        /// <param name="key"></param>

        /// <returns></returns>
        public bool ContainsKey(int key)

        {

            return _entityDictionary.ContainsKey(key);

        }



        /// <summary>

        /// 分页获取实体列表

        /// </summary>

        /// <param name="pageIndex"></param>

        /// <param name="pageSize"></param>

        /// <returns></returns>
        public IList<T> Pagination(int pageIndex, int pageSize)

        {

            int start = (pageIndex - 1) * pageSize;

            int size = Math.Min(pageSize, ItemsCount - start);


            if (start > ItemsCount)

                return new List<T>();


            IList<T> list = new List<T>();


            for (int i = 0; i < size; i++)

                list.Add(_entityDictionary[_indexList[start + i]]);


            return list;

        }


        public IList<T> Pagination(int pageIndex)

        {

            return Pagination(pageIndex, PageSize);

        }


    }

}