背景:
最近正在做一个比较大型的论坛的改版工作。
论坛在高峰期每秒钟约有10个左右的回帖, 3个新帖,论坛的几个热门版面的平均访问量为每天约60wPv。版面帖子的列表页,尤其是列表页的第一页必须是根据帖子的最后回复时间严格排序的;否则用户会找不到自己新发的帖子,或者新回复过的帖子。由于帖子表的数据很大,每次都重新从数据库中取数据肯定会出问题,频繁的读写操作很容易导致死锁。
2种解决方案
1. 直接将版面的前5页数据(假定每页50条数据)即前250条的帖子数据放到内存中,假定声明了一个变量List<PostInfo> newPostList存放这250条的数据;这样有三种情况需要更新这个List变量
1) 当有新帖时需要将第一条帖子插入到List的0索引处
2) 当有帖子被回复时需要首先从List中找到被回复的帖子,如果有就先删除,然后再将回复的帖子插到List的索引0处
3) 当有帖子被删除时需要从List中找到删除的帖子,如果有就remove掉。
上述方案在当前的访问量下,基本可以满足性能要求,但是时不时的有超时现象出现。另外还有一点就是这种进程内的缓存导致论坛不能向外扩展,若使用2台或以上web server就会有列表页数据不一致的现象。所以趁改版也改一下列表页数据读取方式。
2. 为了扩展性,新版改版决定使用memcached做数据缓存,关于列表缓存最直观的改进方式是将方案1中的List放到memcached server中,但是这样每次更新时都需要更新大量数据,网络IO耗时会很严重。另外鉴于memcached擅于快速处理大量小对象缓存,我想这样设计memcached缓存前250条帖子的id的列表假定为List<int> postIdList;在有新帖,新回复,删除等更新时更新postIdList,另外将帖子对象PostInfo实例作为一个项缓存到memcached中,在列表页取数据时,首先取得PostIdList,根据页码得到一个当前页的Id列表,然后通过MemcachedClient.GetMutiple方法获得这些Id对应的PostInfo,如果某些id对应的缓存不存在时,再从数据库中取数据并和缓存中得到的数据合并。
以上两种方案,第一种是运行中的方案,扩展性有问题;第二种方案是构思中的方案,还没有进行实际的测试运行,先晒一下,大家给点意见,建议或新思路。