php + Redis 寫的相似於新浪微博的feed系統

       最近接了一個feed系統的外包,相似於微博那種!客戶端是ios和android,服務器用的php,數據庫用的是redis。分享下服務器和數據庫部分的功能!但願對你們有幫助。php

  關於redis的介紹,你們能夠看這個百度百科 java

    首先是用戶基本信息部分,包含帳號,暱稱,簽名,公司還有頭像,咱們使用redis的hash結構(一種相似於map鍵值對的數據結構)結構以下:(你們在作的時候,仍是用hgetAll的命令,這樣只會有一次的網絡請求),注意只是基本信息,諸如玩家的粉絲,關注和帖子,咱們採起其餘的數據結構體來存儲!android

public function updateUInfo($name,$sign,$head$from)
{
    $redisCli = new Redis(ServerConfig::$redisAddr);
    $redisCli->hSet("user:$this->uid",'sign',$sign);
    $redisCli->hSet("user:$this->uid","name",$name);
    $redisCli->hSet("user:$this->uid","head",$head);
    $redisCli->hSet("user:$this->uid","from",$from);
    
    $redisCli->set("account:$name:uid",$this->uid); 
}

      核心1:關注和粉絲系統!每一個用戶都要維護本身的關注和粉絲系統!分別用user:$uid:followings 和 user:$uid:followers兩個字段體現,使用的是redis的集合類型(至關於java裏面的hashSet和stl中的set,集合中的元素惟一)!ios

     收聽某用戶(mutli是redis提供的一種事務,這樣,就能夠避免產生諸如,你收聽了某人,而猶豫異常,別人的粉絲中缺沒有你的現象)web

public function addFollowing($tid)
{    
    $redisCli = new Redis(ServerConfig::$redisAddr);
    
    if($redisCli->sismember("user:$this->uid:followings",$tid) == 1)
    {
        return ;
    }
    
    $redisCli->multi();
    
    $redisCli->sAdd("user:$this->uid:followings",$tid);
    $redisCli->sAdd("user:$tid:followers",$this->uid);
    
    $redisCli->exec();  
}

  取消收聽某用戶:redis

public function removeFollowings($tid)
{
    $redisCli = new Redis(ServerConfig::$redisAddr);
    
    if($redisCli->sismember("user:$this->uid:followings",$tid) == 0)
    {
        return ;
    }
    
    $redisCli->multi();
    $redisCli->sRem("user:$this->uid:followings",$tid);
    $redisCli->sRem("user:$tid:followers",$this->uid);
    $redisCli->exec();    
}

    核心2:下面談談帖子的更新:數據庫

   首先是帖子的基本數據結構,同上面用戶的基本數據結構,採用redis的hash結構:服務器

class post {
    //put your code here
    
    private $postId = 0;
    
    private $timeStamp = 0;
    
    private $uid = 0;
     
    
    private $content = ""; 
    
    private $subPosts = array();
    
    private $originPostId = -1;
    
    private $tags = array();
    
    
    public function __construct($id,$time,$content,$postId) {
        $this->uid = $id;
        $this->timeStamp = $time;
        $this->content = $content;
        $this->postId = $postId;
    }
    
    public function setOriginPostId($postId)
    {
        $this->originPostId = $postId;
    }
    
    public function getPostId()
    {
        return $this->postId;
    }
    
    public function getTimeStamp()
    {
        return $this->timeStemp;
    }
    
    public function getUid()
    {
        return $this->uid;
    }
    
    public function getContent()
    {
        return $this->content;
    }
     
    
    public function getWebTitle()
    {
        return $this->webTitle;
    }
    
    public function pushPostId($postId)
    {
        $this->subPosts[] = $postId;
    }
    
    public function saveToDb()
    {
        $redisCli = new Redis(ServerConfig::$redisAddr);
        $redisCli->hSet("post:$this->postId","uid",$this->uid);
        $redisCli->hSet("post:$this->postId","time",$this->timeStamp);
        $redisCli->hSet("post:$this->postId","content",$this->content); 
                $redisCli->hSet("post:$this->postId","originPostId",$this->originPostId);
  
        
        $redisCli->set("post:$this->webTitle:$this->postId",$this->postId);
        
        foreach($this->tags as $tag)
        {
            $redisCli->sAdd("post:$this->postId:tags",$tag);
        }
        
        foreach($this->subPosts as $postId)
        {
            $redisCli->lPush("post:$this->postId:subPost",$postId);
        }
        
        
    }
    
}
View Code

  每當用戶發佈一個帖子的時候,他的全部的粉絲必須看獲得他的帖子才能夠!這裏咱們有推和拉兩種方式,對於如今的新浪微博,聽說是採起推和拉結合的兩個方式,咱們的小系統。推:每當用戶發表一個新貼子的時候,就將他的帖子的id主動告知他全部的粉絲。拉:用戶發佈一個新的帖子什麼都不要作,而當他的粉絲請求最新的內容的時候,則須要便利他全部的關注人,取得最新的帖子,而後按照時間排序取出來。推比較消耗內存,拉則是比較消耗cpu。聽說新浪微博採用推和拉結合的方式,好比當一個普通用戶則是推,可是若是是一個大明星有着幾千萬粉絲的大號,當發佈一個帖子的時候,則是須要他的粉絲經過拉的方式來獲取!網絡

  用戶發佈一個新帖子的操做:數據結構

public function post($title,$content,$tags)
{
    $redisCli = new Redis(ServerConfig::$redisAddr);
    
    $postId = postUtil::generateNewPostId();

    $redisCli->Set("user:$this->uid:postTime",time());
    
    $redisCli->lPush("user:$this->uid:news",$post->getPostId());
    
    $followers = $redisCli->sMembers("user:$this->uid:followers");
    foreach($followers as $follower )
    {
        $redisCli->lPush("user:$follower:news",$post->getPostId());
    }
}

    咱們將全部的帖子id推到粉絲的("user:$uid:news")中,這裏採用的是順序隊列結構體!基本也就是按照時間進行了排序(最新的帖子老是左邊)!咱們不會將帖子的內容所有到放到這個字段裏,而是值存放了帖子的id,用戶請求新鮮事的時候,本身再去拉取帖子的內容!

   熱門用戶/熱門帖子,Redis提供了一種有序集合類型,這樣咱們利用這種有序集合類型能夠作熱門,熱門用戶排行和熱門帖子排行!好比咱們能夠根據用戶的粉絲數量作排行,很容易獲得前二十名熱門用戶,根據帖子的閱讀量作熱門帖子的排行了!

   這樣一個簡單的feed系統就算是完成了!可是若是要作大,確實仍是有不少系統要作!

   android客戶端部分的內容,咱們下篇文章見!

相關文章
相關標籤/搜索