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

“[url=http://play3.pcauto.com.cn/auto080228]08北京车展参展美女投票活动[/url]”是我进入太平洋后的第一个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();
}
}
}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值