`
sunny-chance
  • 浏览: 11505 次
  • 性别: Icon_minigender_1
  • 来自: 中山
最近访客 更多访客>>
社区版块
存档分类
最新评论

08北京车展参展美女投票-auto080228

阅读更多
08北京车展参展美女投票活动”是我进入太平洋后的第一个project,代号为auto080228
投票规则描述如下:
1.每个IP每天最多可以投出10票
2.每个IP每天可以对同一个参展美女投多次票
3.每个IP连续对同一个参展美女投票时,投票的时间间隔不得少于10秒
其中,参展美女图片(分大图和小图两种格式)由编辑从后台上传,并设置与之相关的论坛地址

接到任务后,我迫不及待的把表设计出来了:Beauty(beauty_id,name,pic_url_big,pic_url_small,bbs_url,vote_count),其中vote_count即标识参展美女所得票数
后来team leader康哥指出这种设计不合理,“试考虑一下,用户每投一次票,vote_count就要加1,就要更新一次数据库!如果采用(JDO)缓存的话,由于数据更新了,缓存就会清除;每次读取数据的时候都要重新加载,缓存实际上不起作用了。”

针对上面的问题,我乖乖的把Beauty拆分成了两个表
Beauty(beauty_id,name,pic_url_big,pic_url_small,bbs_url,vote_counter_id)---更新少
VoteCounter(vote_counter_id,vote_count) ---用户每投一票更新一次
Beauty表与VoteCounter表是一一对应的关系,在增加投票次数的时候只要更新VoteCounter表即可,不会影响到Beauty表,Beauty的缓存也就不会清除了 。

但回过头来,问题依旧存在,就是写数据库的次数并没有降下来,每投一次票都要更新一次数据库。于是,我采用了缓存投票次数的方法,也就是等到一定的次数(如5次)才更新一次数据库,实现如下:
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.jdo.JDOHelper;

public class VoteCounter extends Sys.DataObject {
	private int cnt;// 票数

	private static final Map CNT_BUFFER = Collections
			.synchronizedMap(new LinkedHashMap(16, 0.75f, false));// 缓存票数

	public int getCnt() {
		return cnt + getBufferedCount();
	}

	public void setCnt(int cnt) {
		this.cnt = cnt;
	}

	/** 获取缓存中的票数 */
	public int getBufferedCount() {
		Object id = JDOHelper.getObjectId(this);
		Integer count = (Integer) CNT_BUFFER.get(id);
		return count != null ? count.intValue() : 0;
	}

	/** 缓存票值,每bufferSize票写一次数据库 */
	public int inc(int bufferSize) {
		int n = 1;// 点击1次加1票
		Object id = JDOHelper.getObjectId(this);

		int bufferedCount = getBufferedCount();
		bufferedCount += n;

		if (bufferedCount >= bufferSize) {
			Object tx = Sys.requireTx();
			cnt += bufferedCount;
			Sys.commit(tx);
			CNT_BUFFER.remove(id);
			return cnt;
		} else {
			CNT_BUFFER.put(id, new Integer(bufferedCount));
			return getCnt();
		}
	}

	/** 保存缓存票值计时任务 */
	static class SaveData extends java.util.TimerTask {
		public void run() {
			Env.log.debug("Running VoteCounter timer task.");
			if (!CNT_BUFFER.isEmpty()) {
				Object tx = Sys.requireTx();
				VoteCounter cnt = null;
				for (Iterator it = CNT_BUFFER.entrySet().iterator(); it
						.hasNext();) {
					Map.Entry me = (Map.Entry) it.next();
					cnt = (VoteCounter) Sys.pm().getObjectById(me.getKey(),
							true);
					cnt.setCnt(cnt.getCnt());
				}
				Sys.commit(tx);
				CNT_BUFFER.clear();
			}
		}
	}
}

这样一来,极大的缓解了数据库的压力。但缺点就是容易丢失投票次数,也会占用一些内存。
为了避免一些冷门的投票长时间占用缓存,后来我也加上了定时器,每隔一段时间把缓存的数据写入数据库...
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics