此文章用来向大家介绍如何使用Reids实现点赞或类似功能,从而达到读写点赞数速度快。
1.PHP代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
$type = isset($_GET['type']) ? intval($_GET['type']) : 2;//类型,1为点赞,2为查询点赞数
$uid = addcslashes($_GET['uid']);//用户id
$ip = $_SERVER['REMOTE_ADDR'];//ip地址
$blog_id = isset($_GET['blog_id']) ? intval($_GET['blog_id']) : '';//博客id
if(empty($blog_id)){//参数为空
$return_data = array(
'code' => 4,
'msg' => 'blog_id can not be empty!',
);
return $return_data;
die;
}
$redis=new Redis();//Redis 实例化
$redis->conncet('127.0.0.1', 6379);
$redis_key = 'upvote';
if($type === 1){//为点赞的
if(empty($uid)){//uid参数不能为空
$return_data = array(
'code' => 4,
'msg' => 'uid can not be empty!',
);
return $return_data;
die;
}
//TODO 防ip redis sorted set
if(!$redis->exists($redis_key.'_fang_ip')){
$redis->zadd($redis_key.'_fang_ip',0,$ip);
}
$ip_count = $redis->zScore($redis_key.'_fang_ip',$ip);
if($ip_count && intval($ip_count)>20){
$return_data = array(
'code' => 3,
'msg' => 'ip dianzan num > 20',
);
return $return_data;
die;
}else{
$redis->zincrby($redis_key.'_fang_ip',1,$ip);
}
//TODO 查看该用户是否存在
//先去redis里查
if(!$redis->sismember($redis_key.'_uid_is_exist',$uid)){
//不存在请求接口
$api_url = '';//
$res = get_url($api_url);
$arr_res = json_decode($res, true);
if ($arr_res['code'] !== 0) {
$return_data = array(
'code' => 5,
'msg' => 'user is not exist!',
);
return $return_data;
die;
}else{
//存进redis set
$redis->sadd($redis_key.'_uid_is_exist',$uid);
}
}
//TODO 查看该用户是否点赞过该楼盘 redis set
if($redis->sismember($redis_key.$blog_id.'_uid',$uid)){
$return_data = array(
'code' => 1,
'msg' => 'user has upvoted',
);
}else{
$redis->sadd($redis_key.$blog_id.'_uid',$uid);//添加该用户到列表
if($redis->zScore($redis_key,$blog_id) === false){
$redis->zadd($redis_key,100,$blog_id);//展示点赞基数(100)
}
$score = $redis->zIncrBy($redis_key,1,$blog_id);//该楼盘点赞数加1,并返回当前的
$return_data = array(
'code' => 0,
'msg' => 'success',
'data' => array(
'blog_id'=> $blog_id,
'score'=> $score
)
);
}
}else{//查询点赞数 redis sorted set
$score = $redis->zScore($redis_key,$blog_id);
if($score == false){
$score = 100;
}
if($uid){
if($redis->sismember($redis_key.$blog_id.'_uid',$uid)){//查看该用户是否点赞过该楼盘
$status = 1;//已经点赞过
}else{
$status = 0;//未点赞过
}
}else{
$status = 0;
}
$return_data = array(
'code' => 0,
'msg' => 'success',
'data' => array(
'blog_id'=> $blog_id,
'score'=> $score,
'status'=> $status
)
);
}
return $return_data;
2.cron,定时更新数据库的数据,并从Redis删除存储ip的key1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 引入mysql 类,实例化
$db = new cls_mysql();
$redis=new Redis();//Redis 实例化
$redis->conncet('127.0.0.1', 6379);
$redis_key = 'upvote';
//如果连不上redis,下次更新
$redis->del($redis_key.'_fang_ip');//删除存储ip的key,一天删除一次
$count = $redis->zCard($redis_key);
$members = $redis->zRange($redis_key,0,$count-1);//取出所有元素
$insert_sql = "insert into upvote (blog_id,score) values ";
$is_has_insert = false;//是否有插入数据
foreach($members as $member){
$score = $redis->zScore($redis_key,$member);
$blog_id = $member;
$sql = "select blog_id from upvote where blog_id='{$blog_id}'";//暂时使用索引覆盖,数量多了 TODO
$res = $db->query($sql,true);
if($res){//有数据时更新
$sql = "update upvote set score='{$score}' where blog_id='{$blog_id}'";
$db->query($sql);
}else{//没数据时添加
$insert_sql .= " ('{$blog_id}','{$score}'),";
$is_has_insert = true;
}
}
if($is_has_insert === true){//如果有插入数据
$insert_sql = trim($insert_sql, ',');
$db->query($insert_sql);
}