php结合Redis实现100万用户投票项目,并实时查看到投票情况的案例
场景:某网站需要对其项目做一个投票系统,投票项目上线后一小时之内预计有100万用户进行投票,希望用户投票完就能看到实时的投票情况
这个场景可以使用redis+mysql冷热数据交换来解决。
何为冷热数据交换?
冷数据:之前使用的数据,热数据:当前使用的数据。
交换:将Redis中的数据周期的存储到MySQL中
业务流程
用户进行投票后,首先将投票数据保存到Redis中,这些数据就是热数据,然后定期(如5s)将热数据保存到MySQL中,这些数据就变为冷数据,然后将冷数据从Redis中删除,周而复始,知道一个小时投票结束。
项目结构图

index.html文件
这是投票的首页,有3个投票按钮,模拟给3个用户投票,点击按钮,使用ajax调用vote.php文件
<!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
<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('123456');
$redis->select(1);//选择数据库1 //计算每个用户的总票数
$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的投票主键(位置)。判断插入的位置是否存在,如果不存在就从头插入,如果全部插入完毕,就进行等待,如果没有插入完毕,就进行插入操作。
<?php
//连接数据库
$pdo = new PDO('mysql:host=39.98.81.13;dbname=try', 'try', 'yn3emW6ksYhwwseh');
$pdo->query('set names utf8'); //连接redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('123456');
$redis->select(1);//选择数据库1
$time = time() + 3600;//时间设置到一小时后
//死循环
while ($time > time()) {
$vid = $redis->get('global_voteid');//自增长的主键
$last = $redis->get('last');//最近一次插入mysql的投票主键
//如果没有插入数据库,刚开始的肯定为true
if (!$last) {
$last = 0;//设置为0
}
//如果所有的数据都被插入到MySQL中
if ($vid == $last) {
echo "wait\n";//输出等待
exit;
} 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';
exit;
}
sleep(20);//每隔20秒执行循环
}
vote表
CREATE TABLE `vote` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
`vid` int(11) unsigned NOT NULL,
`uid` int(11) DEFAULT NULL,
`ip` char(20) DEFAULT NULL,
`time` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8 COMMENT='php结合Redis实现100万用户投票项目表';
运行步骤:
1、运行 swap.php 文件,redis监听投票

linux系统使用php命令行工具调用swap.php (推荐使用这种方法)

2.模拟请求投票

查看redis库有请求记录

20s后查看数据库,投票数据从redis同步到mysql

链接:https://mp.weixin.qq.com/s/7_5ICy-9ZbOD-BcFG2reZQ
php结合Redis实现100万用户投票项目,并实时查看到投票情况的案例的更多相关文章
- 如何通过Dataphin构建数据中台新增100万用户?
欢迎来到数据中台小讲堂!这一期我们来看看,作为阿里巴巴数据中台(OneData - OneModel.OneID.OneService)方法论的产品载体,Dataphin如何帮助传统零售企业实现数字化 ...
- php与Redis实现一个100万用户的投票项目,如何实现实时查看投票情况?
好了,什么是冷热数据交换呢? 很土的解释一下,冷数据就是之前使用的数据,有种过去式的感觉,而热数据就是当前的数据,理解为现在进行时吧.如何交换呢?就是将Redis的数据周期存储到mysql中! 整体的 ...
- 用PHP爬取知乎的100万用户
http://blog.jobbole.com/88788/ 突然发现 大数据 Python的爬虫能力很强 爬取到的数据 直接可以用于维修QQ营销 精准营销
- 从1500万用户巅峰跌落的app,血泪回顾图片社交那些坑
饭桌君说 第八届小饭桌创业课堂来了一位特殊的分享嘉宾,他曾经参与了一款当时极具风头的图片社交app的创始团队,靠谱团队,用户量急速上升到1500万,公司获得A轮……一切看上去都那么美好. 可是,由于各 ...
- Redis & Python/Django 简单用户登陆
一.Redis key相关操作: 1.del key [key..] 删除一个或多个key,如果不存在则忽略 2.keys pattern keys模式匹配,符合glob风格通配符,glob风格的通配 ...
- 用Redis bitmap统计活跃用户、留存
Spool的开发者博客,描述了Spool利用Redis的bitmaps相关的操作,进行网站活跃用户统计工作. 原文:http://blog.getspool.com/2011/11/29/fast-e ...
- 涨姿势:创业做一个App需要花多少钱(8个人,6个月,就要100万,附笔记心得)
(原标题:涨姿势:创业做一个App要花多少钱?) 作为互联网从业者,被外行的朋友们问及最多的问题是,“做一个网站需要多少钱?”或者“做一个APP需要多少钱?”. 作为做过完整网站项目和APP的人,今天 ...
- Stackful 协程库 libgo(单机100万协程)
libgo 是一个使用 C++ 编写的协作式调度的stackful协程库, 同时也是一个强大的并行编程库. 设计之初是为高并发分布式Linux服务端程序开发提供底层框架支持,可以让链接进程序的同步的第 ...
- (转)转一份在 51testing 上的讨论——如何测试一个门户网站是否可以支持10万用户同时在线?
转自:http://www.cnblogs.com/jackei/archive/2006/11/16/561846.html 这个帖子的内容比较典型,大家有兴趣可以也思考一下. 先是楼主提出问题: ...
随机推荐
- 3.自定义返回json格式的数据给前台(自定义Controller类中的Json方法)
在mvc的项目中,我们前台做一些操作时,后台要返回一些结果给前台,这个时候我们就需要有一个状态来标识到底是什么类型的错误, 例如: 执行删除的时候,如果操作成功(1行受影响),我们需要返回状态为1并输 ...
- hdu 1695: GCD 【莫比乌斯反演】
题目链接 这题求[1,n],[1,m]gcd为k的对数.而且没有顺序. 设F(n)为公约数为n的组数个数 f(n)为最大公约数为n的组数个数 然后在纸上手动验一下F(n)和f(n)的关系,直接套公式就 ...
- 【leetcode】636. Exclusive Time of Functions
题目如下: 解题思路:本题和括号匹配问题有点像,用栈比较适合.一个元素入栈前,如果自己的状态是“start”,则直接入栈:如果是end则判断和栈顶的元素是否id相同并且状态是“start”,如果满足这 ...
- mui is not defined
vue项目中引用mui.js,我是在main.js中这样引入的, 结果报错 查找资料,最后在mui.js的最后添加了这样一句 这是因为mui并不能像jquery那样作为全局对象存在,加上wi ...
- 拦截Restful API的三种方式
如题, 方式有三种. (1). 过滤器filter javaEE规范 (2). 拦截器interceptor springmvc提供 (3). 切片 aspect 一. Filter使用示例 impo ...
- tree 解题报告
tree 对于 \(n\) 个点带标号的无根森林,计算所有森林的树的个数的 \(k\) 次方,对 \(998244353\) 取模. 自闭,错了一堆关于长度的问题,这里以后一定要注意 比如需要 \(n ...
- nodejs环境安装
centos7安装nodejs环境 原文地址: https://www.cnblogs.com/MY0101/p/6625344.html 下载地址: https://nodejs.org/dist/ ...
- vue绑定属性、绑定class及绑定style
1.绑定属性 v-bind 或者 : 例如:<img :src="pic_src" /> <template> <div id="app& ...
- 运行python不报错,运行pip报错
Fatal error in launcher: Unable to create process using '""c:\program files (x86)\python36 ...
- pytho装饰器参数那些事_inspect.getcallargs
''' Created on Jul 26, 2019 @author: tomcat ''' import inspect def chack_admin(func): def wrapper(*a ...