yii2 redis队列,数据库表锁实现,点赞功能(10s内只可以点一次)
2017-09-26 18:09
459 查看
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; } }
相关文章推荐
- yii2 redis队列,数据库表锁实现,点赞功能(10s内只可以点一次)
- 一款功能强大并且可以结合html5实现本地存储的数据库 – SQLite学习文档
- Redis队列 实现消息推送功能
- swift--Timer实现定时器功能,每个一段时间执行具体函数,可以重复,也可以只执行一次
- 用thinkphp实现上传文件到数据库的功能并且文件内容不可以重复
- 一款功能强大并且可以结合html5实现本地存储的数据库 – SQLite学习文档
- [置顶] 【Excel_To_DB】SpringBoot+EasyPoi+Redis消息队列实现Excel批量异步导入数据库(三)
- 12.springboot使用redis的订阅功能实现消息队列
- 一款功能强大并且可以结合html5实现本地存储的数据库 – SQLite学习文档
- 如何实现输入字母就可以查出数据库中以该字母匹配的中文实现自动补全功能
- 让redis也能实现数据库才有的増删改、查询过滤功能
- PHP实现的redis主从数据库状态检测功能示例
- redis(jedis)相关API ,实现与关系型数据库相似的功能
- redis 实现消息队列,秒杀功能实现小测试
- [置顶] 【Excel_To_DB】SpringBoot+EasyPoi+Redis消息队列实现Excel批量异步导入数据库(一)
- spring session和Redis数据库实现单点登录功能
- php+redis消息队列实现抢购功能
- Redis源码解析:09redis数据库实现(键值对操作、键超时功能、键空间通知)
- 通过Keepalived实现Redis Failover自动故障切换功能
- php结合redis实现高并发下的抢购、秒杀功能