使用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`命令的
可以點選檢視這個redis zdd命令
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開始查詢,程式碼如下:
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);
}
}
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
總結
通過redis我們實現了互粉的功能,類似的也可以實現評論的功能,這樣我們就能夠緩減mysql的壓力。