场景:某网站需要对其项目做一个投票系统,投票项目上线后一小时之内预计有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万用户投票项目,并实时查看到投票情况的案例的更多相关文章

  1. 如何通过Dataphin构建数据中台新增100万用户?

    欢迎来到数据中台小讲堂!这一期我们来看看,作为阿里巴巴数据中台(OneData - OneModel.OneID.OneService)方法论的产品载体,Dataphin如何帮助传统零售企业实现数字化 ...

  2. php与Redis实现一个100万用户的投票项目,如何实现实时查看投票情况?

    好了,什么是冷热数据交换呢? 很土的解释一下,冷数据就是之前使用的数据,有种过去式的感觉,而热数据就是当前的数据,理解为现在进行时吧.如何交换呢?就是将Redis的数据周期存储到mysql中! 整体的 ...

  3. 用PHP爬取知乎的100万用户

    http://blog.jobbole.com/88788/ 突然发现 大数据 Python的爬虫能力很强 爬取到的数据 直接可以用于维修QQ营销 精准营销

  4. 从1500万用户巅峰跌落的app,血泪回顾图片社交那些坑

    饭桌君说 第八届小饭桌创业课堂来了一位特殊的分享嘉宾,他曾经参与了一款当时极具风头的图片社交app的创始团队,靠谱团队,用户量急速上升到1500万,公司获得A轮……一切看上去都那么美好. 可是,由于各 ...

  5. Redis & Python/Django 简单用户登陆

    一.Redis key相关操作: 1.del key [key..] 删除一个或多个key,如果不存在则忽略 2.keys pattern keys模式匹配,符合glob风格通配符,glob风格的通配 ...

  6. 用Redis bitmap统计活跃用户、留存

    Spool的开发者博客,描述了Spool利用Redis的bitmaps相关的操作,进行网站活跃用户统计工作. 原文:http://blog.getspool.com/2011/11/29/fast-e ...

  7. 涨姿势:创业做一个App需要花多少钱(8个人,6个月,就要100万,附笔记心得)

    (原标题:涨姿势:创业做一个App要花多少钱?) 作为互联网从业者,被外行的朋友们问及最多的问题是,“做一个网站需要多少钱?”或者“做一个APP需要多少钱?”. 作为做过完整网站项目和APP的人,今天 ...

  8. Stackful 协程库 libgo(单机100万协程)

    libgo 是一个使用 C++ 编写的协作式调度的stackful协程库, 同时也是一个强大的并行编程库. 设计之初是为高并发分布式Linux服务端程序开发提供底层框架支持,可以让链接进程序的同步的第 ...

  9. (转)转一份在 51testing 上的讨论——如何测试一个门户网站是否可以支持10万用户同时在线?

    转自:http://www.cnblogs.com/jackei/archive/2006/11/16/561846.html 这个帖子的内容比较典型,大家有兴趣可以也思考一下. 先是楼主提出问题: ...

随机推荐

  1. centos 6.5 关闭防火墙

    关闭防火墙分为临时关闭和永久关闭.临时关闭重启系统后恢复正常,永久关闭重启系统后仍然是关闭状态 临时关闭与开启 service iptables stop service iptables start ...

  2. 【leetcode】75. Sort Colors

    题目如下: 解题思路:我的解题思路是遍历数组,遇到0删除该元素并插入到数组头部,遇到1则不处理,遇到2删除该元素并插入到数组尾部. 代码如下: class Solution(object): def ...

  3. git 配置(实用)

    将公钥添加进入即可  码云是添加私钥(注意!!!!) 这个时候Git就配置好了 git clone ssh协议的仓库 就可以直接拉代码了

  4. Apache搭建http网站服务器入门教程

    Apache搭建http网站服务器入门教程 准备工具 一台带有Linux系统的主机,这里使用CentOS 7.1 64位系统 一个备案过的域名,这里使用www.hellopage.cn 一台可以访问网 ...

  5. [CSP-S模拟测试]:String Master(暴力)

    题目描述 所谓最长公共子串,比如串$A:"abcde"$,串$B:"jcdkl"$,则它们的最长公共子串为串$"cd"$,即长度最长的字符串 ...

  6. vue数据渲染、条件判断及列表循环

    1.数据渲染  {{msg}} <template> <div id="app"> {{msg}} </div> </template&g ...

  7. No orientation specified, and the default is horizontal.异常处理(转)

    参考:http://blog.csdn.net/sky_monkey/article/details/21466975 整的错误提示信息为: No orientation specified, and ...

  8. pytest_用例运行级别_函数级

    '''  函数级(setup_function/teardown_function只对函数用例生 效(不在类中)在类中是用该方法不生效 ''' import pytest def setup_mod ...

  9. Centos 7.3 配置Xmanager XDMCP

    我们通常需要远程桌面,这会带来很好的便利性,而Centos7的XDMCP配置过程发生了变化,添加了很多新特性,初期难免会不适应,但新系统终究还是不错的.下面看看Centos7下如何配置XManager ...

  10. JavaScript 获取function的参数

    function getArgs(func) { // 先用正则匹配,取得符合参数模式的字符串. // 第一个分组是这个: ([^)]*) 非右括号的任意字符 var args = func.toSt ...