本文实例讲述了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