zoukankan      html  css  js  c++  java
  • 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
    ";//输出等待
            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

  • 相关阅读:
    【转+补充】在OpenCV for Android 2.4.5中使用SURF(nonfree module)
    Delphi StarOffice Framework Beta 1.0 发布
    Angular ngIf相关问题
    angularjs文档下载
    公众号微信支付开发
    公众号第三方平台开发 教程六 代公众号使用JS SDK说明
    公众号第三方平台开发 教程五 代公众号处理消息和事件
    公众号第三方平台开发 教程四 代公众号发起网页授权说明
    公众号第三方平台开发 教程三 微信公众号授权第三方平台
    公众号第三方平台开发 教程二 component_verify_ticket和accessToken的获取
  • 原文地址:https://www.cnblogs.com/clubs/p/11806603.html
Copyright © 2011-2022 走看看