redis学习(三) 使用redis构建文章投票,发布后端

1.需求 

 

 1.首先设计数据库

 

 

 2.代码

 Redis.php

<?php


//评分是将文章的到的支持票数乘以一个常量,然后加上文章的发布时间,得出的结果就是文章的评分
const ONE_WEEKS_IN_SECONDS = 7*86400;
//常量是通过一天的秒数(86400)除以文章展示一天所需的支持票数(200)的出的
const VOTE_SCORE =  432;

class Redis1{

    private static $instance;

   // private function __construct(){}  //私有构造,不允许new

    private function __clone(){} //私有克隆方法,不允许通过魔术方法克隆对象

    public  function getIntance($host="127.0.0.1",$port="6379")
    {

        if (!self::$instance instanceof self)
        {
            self::$instance = new Redis();
            self::$instance->connect($host,$port);
        }
        $myredis = self::$instance;
        return $myredis;
    }


    public function index()
    {
        echo "hello world";
    }

    /**
     * 对文章进行投票
     * @param $myredis
     * @param $user
     * @param $article_id
     * @return bool
     */
    public function article_vote()
    {

        $redis = $this->getIntance();
        $article = 'article:24';
        $user = 8;


        $cutoff = time() - ONE_WEEKS_IN_SECONDS;   //计算文章投票截止时间

        if ($redis->zScore('time:',$article) < $cutoff)  //检测是否可以对文章进行投票
        {
            return false;
        }
        $end = strpos($article,'article:');
        $article_id = substr($article,strlen('article:')+$end) ;//从article:id中提取文章的id
        //echo  $article_id;die();
        //如果用户是第一次为这篇文章进行投票,那么增加这篇文章的投票数量和评分
        $first = $redis->sadd('voted:'.$article_id,$user);
        echo 'first';echo $first.'<br>';
        if ($first)
        {
            $score = $redis->zIncrBy('score:',VOTE_SCORE,$article);      //集合添加   给这篇文章加分
            echo "score".$score;
            $vote = $redis->hIncrBy($article,'votes',1);   //hash添加    给这篇文章阅读人数+1
            echo "<br>vote".$vote;
            if ($score && $vote)
            {
                echo "添加成功0";
            }else{
                echo "添加失败0";
            }

        }else{
            echo "添加失败1";
        }

    }


    /**
     * 文章发布功能
     * @param $myredis
     * @param $user
     * @param $title
     * @param $link
     * @return string
     */
    public function post_article()
    {
        //模拟数据
        $user_id = 1;
        $title = "文章标题1";
        $link = "http://www.baidu.com";

        $redis = $this->getIntance();
        $article_id = $redis->incr('article:');  //生成一个新的文章id
        $voted = 'voted:'.$article_id;
        $redis->sAdd($voted,$user_id);            //将发布文章的用户添加到文章的已投票用户名单里面,
        $redis->expire($voted,ONE_WEEKS_IN_SECONDS);  //然后将这个名单的过期时间设置为一周
        $article = 'article:'.$article_id;
        $result = $redis->hMset($article,[       //将文章的信息存到一个散列里面
           'title'=>$title,
           'link'=>$link,
            'poster'=>$user_id,
            'time'=>time(),
            'votes'=>1
        ]);
        echo $article;
        $score = $redis->zAdd('score:',time()+VOTE_SCORE,$article); //将文章添加到根据评分顺序的有序集合里面
        $time = $redis->zAdd('time:',time(),$article);  //将文章添加根据发布时间排序的有序集合和里面

        if ($result && $score && $time)
        {
            echo $article."文章创建成功";exit();
        }else{
            echo $article_id."文章创建失败";exit();
        }
        return $article_id;
    }


    /**
     * 文章获取功能
     * @param $conn
     * @param $page
     * @param string $order
     * @return array
     */
    public function get_articles()
    {
        //$page = $_POST['page']?$_POST['page']:1;
        $page = 1;
        $order="score:";
        $redis = $this->getIntance();
        $ARTICLE_PER_PAGE = 25;
        $start = ($page-1) * $ARTICLE_PER_PAGE;     //设置获取文章的起始索引和结束索引
        $end = $start+ $ARTICLE_PER_PAGE-1;
        $ids = $redis->zRange($order,$start,$end);  //获取多个文章的id

        //var_dump($ids);die();
        $articles = [];
        foreach ($ids as $id)           //根据文章id获取文章详细信息
        {
            $article_data = $redis->hGetAll($id);
            $article_data['id'] = $id;
            $articles[] = $article_data;
        }
        var_dump($articles);die();
        return $articles;
    }

    /**
     * 对文章进行分组
     * @param $conn
     * @param $article_id
     * @param $toadd
     * @param $toremove
     */
    public function add_remove_groups()
    {
        $redis = $this->getIntance();
        $article_id = 23;
        $toadd  = [1,2,3];
        $toremove = [1];
        $article = 'article:'.$article_id;  //构建存储文章信息的键名
        foreach ($toadd as $group)
        {
            $redis->sadd('group:'.$group,$article);   //将文章添加到他所属的群组里面
        }
        foreach ($toremove as $group)
        {
            $redis->srem('group:'.$group,$article);   //从群组里面移除文章
        }
        echo "分组成功";
    }

    /**
     * 分页获取文章数据
     * @param $conn
     * @param $group
     * @param $page
     * @param string $order
     * @return array
     */
    public function get_group_articles()
    {
        $redis = $this->getIntance();
        $order="score:";
        $group = 1;
        $page =1;
        $key = $order.$group; //为每个群组的每种排列顺序都创建一个键
        if (!$redis->exists($key))        //检测是否有已缓存的排序结果,如果没有的话现在就进行排序
        {
            $redis->zinterstore($key,
                ['group:'.$group,$order]
                /*['aggregate'=>'max']*/);    //根据评分或者发布时间对群组文章进行排序
        }
        $redis->expire($key,60);     //让redis60s之后自动删除这个有序集合
        return $this->get_articles($redis,$page,$key);
    }




}

$myredis = new Redis1();
//$myredis->index();
//$myredis->post_article();
//$myredis->get_articles();
//$myredis->article_vote();
//$myredis->add_remove_groups();
$myredis->get_group_articles();

3.待解决问题

1.文章分组(交集和并集)

2.zinterstore的用法

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值