yii2 redis队列,数据库表锁实现,点赞功能(10s内只可以点一次)

8 篇文章 0 订阅
    public function actionLike1(){
        Yii::$app->response->format=Response::FORMAT_JSON;
        if(Yii::$app->request->isGet){
            return [
                'msg'=>'Request Error!',
                'state'=>(int)-1,
            ];
        }
        $data = @json_decode(file_get_contents("php://input","r"),true);
        $topic_id=$data['topic_id'];
        $bool=self::checkTopicId($topic_id);
        if (!$bool){
            return [
                'msg'=>'话题不存在',
                'state'=>'-1',
            ];
        }
        $redis = Yii::$app->redis;
        $ip=Yii::$app->request->getUserIP();
//        $redis->del($topic_id.$ip);
//        $redis->del($topic_id.'likes');
//        $redis->del($topic_id.'log');
        $bool=$redis->exists($topic_id.$ip);
        /*队列最大长度*/
        $max_leng=3;
        /*点赞间隔*/
        $time=1;
        $data=json_encode(['ip'=>$ip,'topic_id'=>$topic_id,'created'=>time()],true);
        if (!$bool){
            //topic_id.ip 不存在,说明可以点赞,<10 加入队列
            if ($leng=$redis->llen($topic_id.'log')<$max_leng){
                $redis->lpush($topic_id.'log',$data);
                //插入成功
                if (!$redis->exists($topic_id.'likes')){
                    //执行sql查询content likes
                    $likes=self::redis_likes($topic_id);
                    //进行点赞了,likes+1
                    $redis->set($topic_id.'likes',$likes+1);
                }else{
                    $redis->incr($topic_id.'likes');
                }
                $likes=$redis->get($topic_id.'likes');
//                var_dump('加入队列',$redis->lrange($topic_id.'log',0,-1));
            }else{
                //大于10
                //事务,log content 入库
                for ($i=0;$i<$max_leng;$i++){
                    $data=$redis->rpop($topic_id.'log');
                    $arr[]=json_decode($data,JSON_UNESCAPED_UNICODE);
                }
                //这一次的加入队列
                $redis->lpush($topic_id.'log',$data);
//                var_dump('加入队列',$redis->lrange($topic_id.'log',0,-1));

                //content likes +10;
                $transaction=Yii::$app->db->beginTransaction(\yii\db\Transaction::SERIALIZABLE);
                try{
                    $sql="select likes from {{%mediacloud_content}} where topic_id=:topic_id for update";
                    $info=Yii::$app->db->createCommand($sql)->bindValue(':topic_id',$topic_id)->queryOne();
                    //现在点赞的人数 +1 因 进行一次请求
                    $likes=$info['likes']+$max_leng+1;
                    /*点赞量入库*/
                    $sql="update {{%mediacloud_content}} set likes=likes+$max_leng WHERE topic_id=:topic_id";
                    Yii::$app->db->createCommand($sql)->bindValue(':topic_id',$topic_id)->execute();
                    //此时数据库 与缓存是一致的
                    $redis->set($topic_id.'likes',$likes);

                    /*log入库*/
                    $bool=Yii::$app->db->createCommand()->batchInsert(LikeLog::tableName(),['ip','topic_id','created'],$arr)->execute();
                    if ($bool==0){
                        throw new Exception('点赞日志入库失败');
                    }
                    $transaction->commit();
                }catch (Exception $e){
//                    var_dump($e->getMessage());
                    $transaction->rollBack();
                    return '点赞失败'.$e->getMessage();
                }
            }
            /*10s内存在说明,不能点赞*/
            $redis->set($topic_id.$ip,'','ex',$time);
            return [
                'msg'=>'ok',
                'state'=>(int)0,
                'likes'=>(int)$likes,
            ];
        }else{
            $likes=$redis->get($topic_id.'likes');
            if (empty($likes)){
                $likes=self::redis_likes($topic_id);
            }
            return [
                'msg'=>'请勿重复点赞',
                'state'=>(int)0,
                'likes'=>(int)$likes,
            ];
        }


    }


    public function actionGetlikes1(){
        Yii::$app->response->format=Response::FORMAT_JSON;
        if (Yii::$app->request->isPost){
            return [
                'msg'=>'Request Error!',
                'state'=>(int)-1,
            ];
        }
        $topic_id=Yii::$app->request->get('topic_id');
        $bool=self::checkTopicId($topic_id);
        if (!$bool){
            return [
                'msg'=>'话题不存在',
                'state'=>'-1',
            ];
        }
        $redis=Yii::$app->redis;
        $likes=$redis->get($topic_id.'likes');
        if (empty($likes)){
            $likes=self::redis_likes($topic_id);
            $redis->set($topic_id.'likes',$likes);
        }
        return [
            'msg'=>'ok',
            'state'=>(int)0,
            'likes'=>(int)$likes,
        ];
    }

    public function redis_likes($topic_id){
        //执行sql查询content likes
        $likes=MediaCloudContent::find()->where(['topic_id'=>$topic_id])->select('likes')->asArray()->one()['likes'];
        //进行点赞了,likes+1
        return $likes;
    }
    public function checkTopicId($topic_id){
        $content=MediaCloudContent::find()->where(['topic_id'=>$topic_id])->select(['topic_id'])->asArray()->one();
        if (!$content){
            return false;
        }else{
            return true;
        }
    }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值