最近在寫api的時候要實現一個相互關注的功能,發現若是用mysql作查詢不是很理想,
因此想能不能用redis來實現這個功能,網上一搜有不少實現的方法,結合網上的博文,實現了本身的功能。html
一下是數據庫的代碼,經過保存用戶的id和關注對象的id以及關注狀態來判斷用戶的關注列
表和粉絲列表,經過聯查獲取用戶的基本信息,入頭像、名稱。mysql
'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='好友數據表'; '
redis提供了不少的類型,這裏咱們使用'zadd'添加有序集合來實現。若是不瞭解'zadd'命令的
能夠點擊查看這個redis zdd命令redis
關注分爲2個步驟,第一部是把對方加入到本身的關注list裏面,第二步是將我寫入到對方
的粉絲中,這裏score是經過時間戳生成的方便以後作分頁查詢,代碼以下sql
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個步驟,第一步從個人關注列表中刪除對方,第二步從對方的粉絲列表中
刪除我,這裏用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; } }
查看關注、粉絲列表原理同樣,用redis的'zrange','zrange'的形式以下api
ZRANGE KEY START STOP
因此咱們傳入要獲取的開始條數'curreng_page',以及要獲取的條數 = 'current_page+page_size-1',
這裏由於redis開始是1因此要-1,而數據庫是從0開始查詢,代碼以下:
redis zrange命令緩存
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); } }
經過redis的'zcard'命令來返回有序集合的數量,也就是粉絲、關注的數量yii
關注狀態分爲3中類型,我當方面關注、你單方面關注、你我相互關注,因此很好理解,只要判斷有序集合中是否存在記錄就能夠了,
這種能夠用到redis的'zcore'命令,this
//我關注你,你沒關注我 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
經過redis咱們實現了互粉的功能,相似的也能夠實現評論的功能,這樣咱們就可以緩減mysql的壓力。code