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客户端部分的内容,我们下篇文章见!

时间: 2025-01-19 15:47:36

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

c++-C++写一个类似于12306的系统 各班次火车信息用什么数据结构好呢

问题描述 C++写一个类似于12306的系统 各班次火车信息用什么数据结构好呢 火车信息包括班次名 票数 各停靠站 以及各停靠站的剩余票数 求指导 我在链表和结构数组之间纠结 解决方案 觉得结构数组好些,一是容易实现,二是理解起来也更容易些,把所有相关信息都放在一个结构体中,用到哪个信息直接调用就好,每个结构体实现对应一个火车班次 解决方案二: 反正你就是做一个学生习作,用什么其实都无所谓,关键看你会什么以及你老师要求你怎么做.数组实现简单,但是长度不易改变,链表比较灵活,但是前提是你要会.如果

capacityFixed 基于jquery的类似于新浪微博新消息提示的定位框_jquery

效果图:当浏览器滚动的时候,要浮层要移除浏览器界面视区的时候,修改其position属性,让其浮动在窗口的上沿显示就可以了,position:fixed,可以在IE7+和其他浏览器下浮动层平滑固定定位,由于IE6前辈不支持fixed属性,使用position:absolute属性代替,重新计算top值. 具体代码如下: HTML代码: 复制代码 代码如下: <div class="float" id="float"> <p id="WB_

javascript实现类似于新浪微博搜索框弹出效果的方法_javascript技巧

本文实例讲述了javascript实现类似于新浪微博搜索框弹出效果的方法.分享给大家供大家参考.具体实现方法如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml

Feed系统架构资料收集

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

java-用Java写一个关于数据库转接的系统,表之间的映射应该怎么做?

问题描述 用Java写一个关于数据库转接的系统,表之间的映射应该怎么做? 现在公司A想将自己的数据插入到公司B,但是两者的表结构并不完全相同,需要做一个转接来完成数据的迁移,我准备用Java来做,现在连接上数据库之后,我需要做一个表与 表之间映射,但是,这个映射应该怎么写啊,宝宝求助各路大神,在此先行谢过 解决方案 直接在数据库上就可以操作啊,根据B公司的表结构,用A公司的表构造一个表,然后导出就可以了, 如果java的话,数据量大可能导致内存溢出,不过可以将读取的数据写入文件,然后再从文件读取

Android -- 固定在ScrollView顶部的View,类似于新浪微博的评论列表的顶部

现在很多App都实现了这个功能,例如新浪微博评论页面的评论.转发.赞的数字可以固定在屏幕上方.我个人很喜欢这种设计,所以利用一点空余时间简单实现了一个类似的功能. 先来看一下上面这张图的效果. 这个是新浪微博的一个页面,整体布局大致分了三块:正文内容.转发评论赞的数字条.评论列表 其中数字条是可以跟着ScrollView一起滑动,但在滑到最顶部时固定在最上面,而下面的评论内容可以继续滑动. 这种效果还是挺赞的,但一开始没有什么思路,所以就去搜了下相关技术代码,一下就恍然大悟!原来是自己想复杂了,

要写一个类似于游戏客服那种的IM,因为第一次接触IM,看环信的官网demo,但是不知道怎么修改里面具体的细节,如果不忙的大神可以加我qq 462694780,帮帮忙

问题描述 解决方案 您是需要使用移动客服还是只是用户与用户之间的聊天?解决方案二:在app端集成环信SDK,设置一个联系客服的入口,进入后与客服管理后台设置的IM服务号创建会话,进入与客服的聊天.具体案例看一下这个商城类的demo:http://docs.easemob.com/doku.php?id=start:475mobilecs:40androidkefudemo这个商城demo下载后再下载iOS的SDK,将EaseMobSDK导入项目,并将lib文件夹的lite.a包删除即可运行.移动

PostgreSQL 异步消息实践 - 亿级/分钟 FEED系统实时监测

标签 PostgreSQL , 异步消息 , 触发器 , 规则 , insert on conflict , 实时分析 背景 在很多业务系统中,为了定位问题.运营需要.分析需要或者其他需求,会在业务中设置埋点,记录用户的行为在业务系统中产生的日志,也叫FEED日志. 比如订单系统.在业务系统中环环相扣,从购物车.下单.付款.发货,收货(还有纠纷.退款等等),一笔订单通常会产生若干相关联的记录. 每个环节产生的属性可能是不一样的,有可能有新的属性产生,也有可能变更已有的属性值. 为了便于分析,通常

nginx+redis 实现 jsp页面缓存,提升系统吞吐率

最近在开发的时候,发现之前APP客户端的一部分页面用的是webview交互,这些页面请求很多,打开一套试卷,将会产生100+的请求量,导致系统性能下降.于是考虑在最靠近客户端的Nginx服务器上做Redis缓存.综合了下网上对于php缓存的资料,经过一番改动,终于搭建成功.由于网上的是针对php的,而且没有说明,对于我这种完全不动运维的人来说,研究下来还是挺痛苦的.所以整理一份比较完整的,供大家参考. 以下的配置中,可能有不适合或者写的有问题的.请留言指出,谢谢! 最终缓存以后,整个项目结构图如