使用redis實現互粉功能

tigermmm 7年前發布 | 44K 次閱讀 Redis NoSQL數據庫

使用redis實現互粉

最近在寫api的時候要實現一個相互關注的功能,發現如果用mysql做查詢不是很理想,

所以想能不能用redis來實現這個功能,網上一搜有很多實現的方法,結合網上的博文,實現了自己的功能。

1.數據庫實現

一下是數據庫的代碼,通過保存用戶的id和關注對象的id以及關注狀態來判斷用戶的關注列

表和粉絲列表,通過聯查獲取用戶的基本信息,入頭像、名稱。

'DROP TABLE IF EXISTS `shc_sns`;
 CREATE TABLE `shc_sns` (
   `sns_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id值',
   `sns_frommid` int(11) NOT NULL COMMENT '會員id',
   `sns_tomid` int(11) NOT NULL COMMENT '朋友id',
   `sns_addtime` int(11) NOT NULL COMMENT '添加時間',
   `sns_followstate` tinyint(1) NOT NULL DEFAULT '1' COMMENT '關注狀態 1為單方關注 2為雙方關注',
   PRIMARY KEY (`sns_id`),
   KEY `FROMMID` (`sns_frommid`) USING BTREE,
   KEY `TOMID` (`sns_tomid`,`sns_frommid`) USING BTREE,
   KEY `FRIEND_IDS` (`sns_tomid`) USING BTREE
 ) ENGINE=InnoDB AUTO_INCREMENT=196 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='好友數據表';
'

2.使用redis實現

redis提供了很多的類型,這里我們使用'zadd'添加有序集合來實現。如果不了解'zadd'命令的

1.關注

關注分為2個步驟,第一部是把對方加入到自己的關注list里面,第二步是將我寫入到對方

的粉絲中,這里score是通過時間戳生成的方便之后做分頁查詢,代碼如下

public function addFollowsFansById($data){
         if(empty($data)) return false;
         $data['sns_addtime'] = time();
         if($data['sns_followstate'] == 1){//單方面關注
             $result = $this->addFollowFan($data);//添加到數據庫
             if($result){//添加到有序集合
                 $this->cache->redis->zAdd('shc_follow:'.$data['sns_frommid'],time(),$data['sns_tomid']);
                 $this->cache->redis->zAdd('shc_fans:'.$data['sns_tomid'],time(),$data['sns_frommid']);
             }
             return true;
         }elseif($data['sns_followstate'] == 2){//相互關注
             $this->db->trans_begin();
             $this->addFollowFan($data);
             $this->editFollowFans(['sns_frommid'=>$data['sns_tomid'],'sns_tomid'=>$data['sns_frommid']],['sns_followstate'=>2]);
             if($this->db->trans_status() === false){
                 $this->db->trans_rollback();
                 return false;
             }else{
                 $this->db->trans_commit();
                 $this->cache->redis->zAdd('shc_follow:'.$data['sns_frommid'],time(),$data['sns_tomid']);
                 $this->cache->redis->zAdd('shc_fans:'.$data['sns_tomid'],time(),$data['sns_frommid']);
                 return true;
             }
         }else{
             return false;
         }
     }

2.取消關注

取消關注也分為2個步驟,第一步從我的關注列表中刪除對方,第二步從對方的粉絲列表中

刪除我,這里用redis的'zrem'來實現從有序集合中刪除記錄, redis zrem命令

public function deleteFollowFansById($user_id,$follow_id,$state){
        if($state == 1){
            $result = $this->deleteFollowFans(['sns_frommid'=>$user_id,'sns_tomid'=>$follow_id]);
            if($result){//緩存刪除關注
                $this->cache->redis->zRem('shc_follow:'.$user_id,$follow_id);
                $this->cache->redis->zRem('shc_fans:'.$follow_id,$user_id);
            }
            return true;
        }elseif($state == 2){
            //開啟事務
            $this->db->trans_begin();
            $this->deleteFollowFans(['sns_frommid'=>$user_id,'sns_tomid'=>$follow_id]);
            $this->editFollowFans(['sns_frommid'=>$follow_id,'sns_tomid'=>$user_id],['sns_followstate'=>1]);
            if($this->db->trans_status() === false){
                $this->db->trans_rollback();
                return false;
            }else{
                $this->cache->redis->zRem('shc_follow:'.$user_id,$follow_id);
                $this->cache->redis->zRem('shc_fans:'.$follow_id,$user_id);
                $this->db->trans_commit();
                return true;
            }
        }else{
            return false;
        }
    }

3.查看關注列表、粉絲列表

查看關注、粉絲列表原理一樣,用redis的'zrange','zrange'的形式如下

ZRANGE KEY START STOP

所以我們傳入要獲取的開始條數'curreng_page',以及要獲取的條數 = 'current_page+page_size-1',

這里因為redis開始是1所以要-1,而數據庫是從0開始查詢,代碼如下:

 

public function getFollowsListById($user_id,$limit=array()){
        $follow_list = $this->cache->redis->zRevRange('shc_follow:'.$user_id,$limit['current_page'],$limit['current_page']+$limit['page_size']-1);
        if($follow_list){
            $member_list = $this->Member_Model->getMemberListByIdS($follow_list,'user_id,user_nickname,user_portrait');
            if($member_list) return $member_list;
        }else{
            return $this->getFollowsListByDb(['a.sns_frommid'=>$user_id],'b.user_id,b.user_nickname,b.user_portrait',$limit);
        }
    }

4.關注、粉絲數量

通過redis的'zcard'命令來返回有序集合的數量,也就是粉絲、關注的數量

5.關注狀態

關注狀態分為3中類型,我當方面關注、你單方面關注、你我相互關注,所以很好理解,只要判斷有序集合中是否存在記錄就可以了,

這種可以用到redis的'zcore'命令,

//我關注你,你沒關注我
ZSCORE 1:follow 2 #ture
ZSCORE 1:fans 2 #false

//你關注我,我沒關注你 ZSCORE 1:follow 2 #false ZSCORE 1:fans 2 #true

//相互關注 ZSCORE 1:follow 2 #true ZSCORE 1:fans 2 #true</code></pre>

總結

通過redis我們實現了互粉的功能,類似的也可以實現評論的功能,這樣我們就能夠緩減mysql的壓力。

 

來自:https://segmentfault.com/a/1190000008145959

 

 本文由用戶 tigermmm 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!