本文实例讲述了php结合redis+mysql实现冷热数据交换应用案例。分享给大家供大家参考,具体如下:
场景:某网站需要对其项目做一个投票系统,投票项目上线后一小时之内预计有100万用户进行投票,希望用户投票完就能看到实时的投票情况
这个场景可以使用redis+mysql冷热数据交换来解决。
何为冷热数据交换?
冷数据:之前使用的数据,热数据:当前使用的数据。
交换:将redis中的数据周期的存储到mysql中
业务流程
用户进行投票后,首先将投票数据保存到redis中,这些数据就是热数据,然后定期(如5s)将热数据保存到mysql中,这些数据就变为冷数据,然后将冷数据从redis中删除,周而复始,知道一个小时投票结束。
项目结构图
index.html文件
这是投票的首页,有3个投票按钮,模拟给3个用户投票,点击按钮,使用ajax调用vote.php文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<!doctype html public "-//w3c//dtd xhtml 1.0 strict//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-strict.dtd" >
<html xmlns= "http://www.w3.org/1999/xhtml" xml:lang= "en" >
<head>
<meta http-equiv= "content-type" content= "text/html;charset=utf-8" >
<title>document</title>
</head>
<script src= "http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js" ></script>
<body>
<p><span id= "uid1" >0</span><input type= "button" value= "用户1" onclick= "vote(1);" /></p>
<p><span id= "uid2" >0</span><input type= "button" value= "用户2" onclick= "vote(2);" /></p>
<p><span id= "uid3" >0</span><input type= "button" value= "用户3" onclick= "vote(3);" /></p>
</body>
<script>
function vote(i){
$.get( 'vote.php?uid=' +i, function (rs){
var span = '#uid' +i;
$(span).html(rs);
});
}
</script>
</html>
|
vote.php
这个文件主要实现投票的逻辑。首先连接上redis服务器,然后保存投票人id,然后将投票人id为key记录每个用户的票数,然后返回给index.html文件,最后使用global_voteid作为key记录总票数,也可以作为mysql的自增长的键。然后记录uid,ip,time等数据。
注意格式有一定的要求:
假如voteid为3,记录的是ip,那么键为vote:3:ip:127.0.0.1
1
2
3
4
5
6
7
8
9
10
11
12
|
<?php
$redis = new redis();
$redis ->connect( 'localhost' ,6379);
//计算每个用户的总票数
$uid = intval ( $_get [ 'uid' ]);
//$uid = mt_rand(1,3);//随机指定投票人员,方便进行压力测试
echo $redis ->incr( $uid );
$voteid = $redis ->incr( 'global_voteid' );
$redis ->set( 'vote:' . $voteid . ':uid' , $uid );
$ip = $_server [ 'remote_addr' ];
$redis ->set( 'vote:' . $voteid . ':ip' , $ip );
$redis ->set( 'vote:' . $voteid . ':time' ,time());
|
重点内容
这个文件主要实现冷热数据交换,首先连接mysql数据库和redis服务器,然后每隔5秒去执行while循环,在while循环里获取自增长的投票主键和最近一次插入mysql的投票主键(位置)。判断插入的位置是否存在,如果不存在就从头插入,如果全部插入完毕,就进行等待,如果没有插入完毕,就进行插入操作。
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
|
<?php
//连接数据库
$pdo = new pdo( 'mysql:host=localhost;dbname=test' , 'root' , '1234' );
$pdo ->query( 'set names utf8' );
//连接redis
$redis = new redis();
$redis ->connect( 'localhost' ,6379);
//永真循环
while (true){
$vid = $redis ->get( 'global_voteid' ); //自增长的主键
$last = $redis ->get( 'last' ); //最近一次插入mysql的投票主键
//如果没有插入数据库,刚开始的肯定为true
if (! $last ){
$last = 0; //设置为0
}
//如果所有的数据都被插入到mysql中
if ( $vid == $last ){
echo "wait\n" ; //输出等待
} else {
//进行插入到数据库操作
$sql = 'insert into vote(vid,uid,ip,time) values' ;
for ( $i = $vid ; $i > $last ; $i --){
$k1 = 'vote:' . $i . ':uid' ;
$k2 = 'vote:' . $i . ':ip' ;
$k3 = 'vote:' . $i . ':time' ;
$row = $redis ->mget([ $k1 , $k2 , $k3 ]);
$sql .= "($i,$row[0],'$row[1]',$row[2])," ;
$redis -> delete ( $k1 , $k2 , $k3 );
}
$sql = substr ( $sql ,0,-1);
$pdo -> exec ( $sql );
$redis ->set( 'last' , $vid ); //设置插入的主键位置
echo 'ok' ;
}
sleep(5); //每隔5秒执行循环
}
|
vote表
运行步骤:
1、使用php命令行工具调用swap.php
2、使用apache的ab工具进行压力测试。
希望本文所述对大家PHP程序设计有所帮助。
原文链接:https://blog.csdn.net/baochao95/article/details/60761397