• Redis实战之文章投票(php实现)


    投票代码PHP实例

    增加投票事务控制

    思路讲解:

    * 投票有效期为  86400*7
    * 一个赞的分值为 86400 / 200  = 432
    *
    * hash 存储文章的内容, key为文章的id
    * zset key为文章id,score为文章发布时间,存时间戳
    * zset key为文章id,score为文章的分值
    * set 记录投票用户与对应文章
    

    完整代码:

    
    <?php
    /**
     * Created by PhpStorm.
     * User: Administrator
     * Date: 2021/9/8
     * Time: 10:01
     */
    class Vote
    {
        private $redis;
        const SCORE = 432;      // 此方式可以在输出文章详情的给出,这里没有计算
        const VOTE_EXPIRE_TIME = 86400 * 7;
        const PARAM_ERROR = '参数错误';
        public function __construct()
        {
            $this->redis = new Redis();
            $this->redis->connect('172.17.0.3','6379','5');
            //$this->redis->connect('127.0.0.1','6379','5');
            $this->redis->select(7);
        }
    
        // 发布文章
        public function postArticle($content) {
            $author_id = $content['poster'];         // 作者id
            // 这里使用了incr自增的操作
            $article_id = $this->redis->incr('article:');   // 文章id
            // 添加文章
            $article_key = 'article:'.$article_id;
    
            // 文章发布开启一个事务
            $this->redis->hMSet($article_key, $content);
            // 将文章添加到发布时间有序集合中
            $this->redis->zAdd("time:",time(),$article_key);
            // 将文章添加到分数有序集合中
            $this->redis->zAdd("score:",1, $article_key);
            // 创建投票集合,并将作者添加进去
            $this->redis->sAdd("vote:".$article_id, $author_id);
            // 设置投票集合的有效期
            $this->redis->expire("vote:".$article_id, self::VOTE_EXPIRE_TIME);
            return $article_id;
        }
    
        // 给文章投票
        // $vote_id     投票用户id
        // $article_id  文章id
        public function voteArticle($vote_id, $article_id) {
            $article_key = 'article:'.$article_id;
            $vote_key = 'vote:'.$article_id;
            // 判断文章是否存在
            if (!$this->redis->exists($article_key)) {
                echo '未找到文章信息!';
                exit();
            }
            // 判断是否过投票期
            $cutOff = time() - self::VOTE_EXPIRE_TIME;
            $post_time = $this->redis->zScore("time:",$article_key);
            if ($post_time < $cutOff) {
                echo '投票时间已过!';
                exit();
            }
            try {
                $this->redis->watch($article_key);              // 监视文章的key,一旦发生改变就跳出
                if ($this->redis->sIsMember($vote_key, $vote_id)) {
                    $this->redis->unwatch($vote_key);
                    echo '已投票!不能重复投票';
                    exit();
                }
                $this->redis->multi();
                $this->redis->sAdd($vote_key,$vote_id);
                $this->redis->zIncrBy("score:",1, $article_key);
                $this->redis->hIncrBy($article_key,'votes',1);
                $this->redis->exec();
                echo "投票成功";
                exit();
            } catch (Exception $e) {
                throw new Exception($e->getMessage());
            }
        }
    
        // 获取文章列表
        public function getArticle($page = 1, $size = 10, $order='score:') {
            $start = ($page - 1) * $size;
            $end = $start + $size - 1;
            $ids = $this->redis->zRevRange($order, $start, $end);
            foreach ($ids as $id) {
                $data = $this->redis->hGetAll($id);
                $data['article_id'] = $id;
                $articles[] = $data;
            }
            return $articles;
        }
    
    
        // 将文章加入到不同的分组中,或者从分组中移除
        public function addOrRemoveGroup($article_id, $group_id=[], $type = 'add') {
            $article_key = "article:".$article_id;
            $op = $type=='add' ? 'sAdd' : 'sRem';
            foreach ($group_id as $item) {
                $this->redis->$op("group:".$item, $article_key);
            }
            echo $op . '成功';
        }
    
        // 获取不同分组的文章
        public function getGroupArticle($orders="score:", $group_id) {
            $save_key = "new_group:".$orders . $group_id.":".session_id();
            if (!$this->redis->exists($save_key)) {
                $this->redis->zinterstore($save_key, ["group:".$group_id, $orders]);
            }
            $list = $this->getArticle(1,3, $save_key);
            $this->redis->del($save_key);
            return $list;
        }
    
    }
    
    // 测试部分
    
    // 分组 1-redis 2-php 3-mysql
    $vote = new Vote();
    // 这里数据可以重复构造
    /*$article_content = [
        'title' => 'mysql基础_2',
        'link' => 'http://www.baidu.com',
        'poster' => 'user:2',
        'time' => time(),
        'votes' => 1
    ];
    print_r($vote->postArticle($article_content));*/
    // 投票
    //echo $vote->voteArticle("user:1",1);
    // 获取文章列表
    /*$list = $vote->getArticle(1,3,"time:");
    echo "<pre>";
    print_r($list);
    echo "<pre>";*/
    
    // 文章分组
    //$vote->addOrRemoveGroup(1,[1],'add');
    //$vote->addOrRemoveGroup(3,[1],'add');
    
    // 输出分组文章
    /*$list = $vote->getGroupArticle("score:",1);
    echo "<pre>";
    print_r($list);
    echo "<pre>";*/
    
    
    想生活,不想谋生
  • 相关阅读:
    angularJS
    WebSocket通信协议
    重写ajax方法实现异步请求session过期时跳转登录页面
    npm(cnpm)介绍(安装gulp)
    grunt安装与配置
    前端学习之jquery
    前端基础之CSS
    前端基础html
    激活
    socket 网络通信(基于tcp协议)以及粘包解决方案
  • 原文地址:https://www.cnblogs.com/Daneil/p/15182968.html
Copyright © 2020-2023  润新知