项目背景:为1000多名用户投票
说明:尽量减少服务器和数据库压力
方案:静态数据(头像,用户名,职业等信息)和动态数据(票数)分离获取,首先加载基础数据(头像,用户名,职业等信息)界面展示,然后jquery异步获取票数,静态数据和动态数据分别用Redis缓存更新,减小数据库压力和响应时间
1.静态数据缓存
这里当时是按分页缓存的,md5(排序和分页)作redis的key,不作说明了
2.动态数据缓存
2.1前台按顺便取id集合(array_column($result,'id'),$result为结果集),jquery异步提交查询
2.2后台接口取到id集合(注:这里用户的票数是按标识+id作key来存储票数的,“xxx-id”),以下为用id集合在redis找票数的思路
............
//交换键值
$flip_ids=array_flip($ids);
//赋值原数组
$_ids=$ids;
//添加key前缀
foreach ($ids as $k=>$v){
$ids[$k]="xxx-{$v}";
}
$ids_val=$redis->mget($ids);
//取值为false的下标(没找到用户得票数)
$ids_val_false=array_keys($ids_val,false,true);
if($ids_val_false){
//取值为false的id
foreach ($ids_val_false as $v){
//找id(用户ID)
$wheretid[]=$_ids[$v];
}
//链接数据库,从数据库取redis没找到的得票数
$result=$obj->query_fetch_all("select id,votes from table where ... id IN (".implode(",",$wheretid).')');
if($ids_val||$result){
$setRed=array();
if($result){
foreach ($result as $v){
//按顺序替换值为false的值
$ids_val[$flip_ids[$v['tid']]]=$v['votes'];
//设置key-value
$setRed['xxx-'.$v['id']]=$v['votes'];
}
}else{
foreach ($wheretid as $v){
//按顺序替换值为false的值
$ids_val[$flip_ids[$v]]=0;
//设置key-value
$setRed['xxx-'.$v]=0;
}
}
$redis->mset($setRed);
}else{
echo json_encode(array('code'=>1,'value'=>0));exit;
}
}
$redis=null;
//按顺序返回
echo json_encode(array('code'=>1,'value'=>$ids_val));exit;
3.js处理返回的数据
...............
<label class="votes-num">获取中...</label>
...............
..........
$.post(url,{param:_param},function (r) {
if(r.code==1){
var arr=r.value;
if(arr===0){
$('label.votes-num').html('0票');
}else{
$('label.votes-num').each(function(k,v){
$(this).html(arr[k]+'票');
});
}
}else{
alert(r.value);
}
},'json');
..........
4.这里涉及投票数据插入(更新redis和数据库用户的得票数);前后台交互必要的验证手段,防止恶意请求;更重要的是验证码,很有必要加,验证码或第三方验证平台(极验,点触),当初使用的是极验,因为当时点触在手机验证界面不满足需求,操作步骤多缺乏关闭回调函数,当时已反馈给点触做功能扩展,以下为当时极验验证一个ID的数据。
PS:验证码也只是个辅助手段,毕竟还是有打码平台可以操作的,我觉得论当时的配置直接sql过去sql过来是没问题的,哈哈.......但是本着朝好的方面发展还是用了缓存的,以上思路就是在当时急需的情况下想到的方案,没的问题,唯一有问题的是极验让给钱了,不是封了我们免费的,最后就换成TP提取出来的验证码了,主要太贵了,上面不舍得花,呵呵。