php + Redis 写的类似于新浪微博的feed系统

最近接了一个feed系统的外包,类似于微博那种!客户端是ios和android,服务器用的php,数据库用的是redis。分享下服务器和数据库部分的功能!希望对大家有帮助。

  关于redis的介绍,大家可以看这个百度百科

    首先是用户基本信息部分,包含账号,昵称,签名,公司还有头像,我们使用redis的hash结构(一种类似于map键值对的数据结构)结构如下:(大家在做的时候,还是用hgetAll的命令,这样只会有一次的网络请求),注意只是基本信息,诸如玩家的粉丝,关注和帖子,我们采取其他的数据结构体来存储!

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,集合中的元素唯一)!

收听某用户(mutli是redis提供的一种事务,这样,就可以避免产生诸如,你收听了某人,而犹豫异常,别人的粉丝中缺没有你的现象)

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();
}

  取消收听某用户:

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);
        }

    }

}

  每当用户发布一个帖子的时候,他的所有的粉丝必须看得到他的帖子才可以!这里我们有推和拉两种方式,对于现在的新浪微博,据说是采取推和拉结合的两个方式,我们的小系统。推:每当用户发表一个新贴子的时候,就将他的帖子的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客户端部分的内容,我们下篇文章见!

 

时间: 2024-07-31 13:40:00

php + Redis 写的类似于新浪微博的feed系统的相关文章

用node加redis实现follow,tag,feed系统

https://cnodejs.org/topic/53ad78f2c3ee0b5820f74298 follow,tag,和feed系统都非常适合用redis来实现,以tag系统为例: 用户ltebean要给nodejs加一个标签amazing就是: sadd user:ltebean:tag:amazing nodejs sadd user:ltebean:item:nodejs amazing 存一个反向关系是为了即能根据tag查也能根据item查,下面是redis的command: 拿到

redis写shell与ssh免密码登陆

redis-cli参数:-h :指定要连接的主机IP或域名-p :指定连接的端口-a :指定密码-r :执行指定的命令-n :数据库名-x :将最后一个参数输出为value redis写shell-----端口6379 redis-cli -h 127.0.0.1config set dir ar/www/webroot/config set dbfilename redis.phpset webshell "<?php phpinfo();?>"save ssh-keyg

Feed系统架构资料收集

完全用nosql轻松打造千万级数据量的微博系统 微博feed系统的push和pull模式和时间分区拉模式架构探讨 关于如何构建一个微博型广播 关于如何构建一个微博型广播2 用 mongodb 储存多态消息/提醒类数据 构建高性能的微博系统-再谈新浪微博架构 人人网技术经理张铁安-Feed系统结构浅析 新浪微博Cache设计@TimYang.pdf 人人网技术经理张铁安-Feed系统结构浅析 新浪微博基于MySQL的分布式数据库实践 杨卫华谈新浪微博架构:MySQL和NoSQL Sina微博构架师

百万用户时尚分享网站feed系统扩展实践

Fashiolista是一个在线的时尚交流网站,用户可以在上面建立自己的档案,和他人分享自己的以及在浏览网页时看到的时尚物品.目前,Fashiolista的用户来自于全球100多个国家,用户达百万级,每日分享的时尚物品超过500万.作为一个以社交.分享的网站,feed系统占据了网站的核心架构,Fashiolista的创始人兼CTO Thierry Schellenbach撰写了一篇博客,分享了自家网站feed系统建设的经验,译文如下: Fashiolista最初是我们作为兴趣在业余时间开发的一个

Feed系统架构资料收集(转)

add by zhj:有些链接已经失效,后续会修改. 原文:http://blog.csdn.net/zhangzhaokun/article/details/7834797 完全用nosql轻松打造千万级数据量的微博系统 微博feed系统的push和pull模式和时间分区拉模式架构探讨 关于如何构建一个微博型广播 关于如何构建一个微博型广播2 用 mongodb 储存多态消息/提醒类数据 构建高性能的微博系统-再谈新浪微博架构 人人网技术经理张铁安-Feed系统结构浅析 新浪微博Cache设计

人人网张铁安:Feed系统架构分析(转)

原文:http://www.csdn.net/article/2010-07-26/277273 继成功举办首期TUP活动后,日前在北京丽亭华苑酒店鸿运二厅,由CSDN和<程序员> 杂志联合策划组织的TUP第二次活动如期而至,本次活动以Web 2.0技术为主题,聚焦当下火热的社交网.微博架构与实时搜索领域.就相关领域及产品研发背后的技术.产品设计及用户体验话题为与会者提供全开放式的交流 平台.即使是付费沙龙,参会报名人数仍在不断上升,本次活动有超过300人来到现场. 人人网技术经理张铁安 以下

2.3为方便旅客,某航空公司拟开发一个机票预定系统。 写出问题定义并分析系统的可行性。

为方便旅客,某航空公司拟开发一个机票预定系统.旅行社把预定机票的旅客信息(姓名.性别.工作单位.身份证号码.旅行时间.旅行目的地等)输入进 入该系统,系统为旅客安排航班,印出取票通知和账单,旅客在飞机起飞的前一天凭取票通知和账单交款取票,系统校对无误即印出机票给旅客. 写出问题定义并分析系统的可行性. 1>     目标:在一个月内建立一个高效率,无差错的航空公司机票预定系统 2>     存在的主要问题:人工不易管理,手续繁琐 3>     建立新系统 ①  经济可行性        

Linux系统的rm命令太危险,一不小心就会删除系统文件。写一个shell脚本来替换系统的rm命令,

Linux系统的rm命令太危险,一不小心就会删除系统文件.写一个shell脚本来替换系统的rm命令,要求当删除一个文件或者目录时都要做一个备份,然后再删除. 假设有一个大的分区/data/,每次删除文件或者目录前,都要在/data/下面创建一个隐藏目录,以日期/时间命名,比如/data/.201802021054,然后把所有删除的文件同步到该目录下面,可以使用rsync -R把文件路径一同同步 答案: #!/bin/bash d=`date +%Y%m%d%H%M` read -p "Are y

实体写到redis写不进去--误把类当成实体类

之前一直都把实体写入redis都没有问题,今天再次这样干,结果却是怎么写都写不进去,redis里的值老是为空 最后才发现把类当成了实体类,当然写不进去了. 把类: /// <summary>    /// Redis实体    /// </summary>    public class Redis    {        public string tdtype;//tdtype        public string tdaccount;//tdaccount