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客户端部分的内容,我们下篇文章见!
php + Redis 写的类似于新浪微博的feed系统的更多相关文章
- 利用redis写webshell
		
redis和mongodb我之所见 最近自己在做一些个人的小创作.小项目,其中用到了mongodb和redis,最初可能对这二者没有深入的认识.都是所谓的“非关系型数据库”,有什么区别么? 实际上,在 ...
 - redis写shell与ssh免密码登陆
		
redis-cli参数:-h :指定要连接的主机IP或域名-p :指定连接的端口-a :指定密码-r :执行指定的命令-n :数据库名-x :将最后一个参数输出为value redis写shell- ...
 - Feed系统架构资料收集
		
完全用nosql轻松打造千万级数据量的微博系统 微博feed系统的push和pull模式和时间分区拉模式架构探讨 关于如何构建一个微博型广播 关于如何构建一个微博型广播2 用 mongodb 储存多态 ...
 - 百万用户时尚分享网站feed系统扩展实践
		
Fashiolista是一个在线的时尚交流网站,用户可以在上面建立自己的档案,和他人分享自己的以及在浏览网页时看到的时尚物品.目前,Fashiolista的用户来自于全球100多个国家,用户达百万级, ...
 - Feed系统架构资料收集(转)
		
add by zhj:有些链接已经失效,后续会修改. 原文:http://blog.csdn.net/zhangzhaokun/article/details/7834797 完全用nosql轻松打造 ...
 - Redis进阶实践之二如何在Linux系统上安装安装Redis
		
一.引言 上一篇文章写了"如何安装VMware Pro虚拟机"和在虚拟机上安装Linux操作系统.那是第一步,有了Linux操作系统,我们才可以在该系统上安装Redis. ...
 - Redis进阶实践之六Redis Desktop Manager连接Windows和Linux系统上的Redis服务(转载6)
		
Redis进阶实践之六Redis Desktop Manager连接Windows和Linux系统上的Redis服务 一.引言 今天本来没有打算写这篇文章,但是,今天测试Redis的时候发现了两个问题 ...
 - Redis进阶实践之三如何在Windows系统上安装安装Redis(转载)
		
Redis进阶实践之三如何在Windows系统上安装安装Redis 一.Redis的简介 Redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括 ...
 - Redis进阶实践之二如何在Linux系统上安装安装Redis(转载)(2)
		
Redis进阶实践之二如何在Linux系统上安装安装Redis 一.引言 上一篇文章写了“如何安装VMware Pro虚拟机”和在虚拟机上安装Linux操作系统.那是第一步,有了Linux操作系统,我 ...
 
随机推荐
- 如何通过Socket TCP发送并接收一个文件?
			
一.小结 1.大包发小包收,只发一次. 2.发时把文件扩展名,文件长度也随同一起发送,方便接收端接收时另存为正确的文件类型,并判断是否已经接收完毕. 如果不一起发送,分为文件扩展名,文件长度,文件内容 ...
 - OpenCV仿射变换+投射变换+单应性矩阵
			
本来想用单应性求解小规模运动的物体的位移,但是后来发现即使是很微小的位移也会带来超级大的误差甚至错误求解,看起来这个方法各种行不通,还是要匹配知道深度了以后才能从三维仿射变换来入手了,纠结~ esti ...
 - WPF 设置程序开机自动运行(+注册表项)
			
#region 设置程序开机自动运行(+注册表项) RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Micr ...
 - Ecshop 最小起订量如何设置
			
第一步,商品表必须有个字段 代表某个商品 最小订购数量->min_number 打开goods表 在最后字段添加一个min_number tinyint类型 默认值为0 代表没有最小起 ...
 - android studio 中查找代码中的硬编码
			
在Android Studio中同时按下Ctrl + Shift+ F 或者其他自定义的快捷键,打开全局搜索,在全局搜索中输入 ^((?!(\*|//)).)+[\u4e00-\u9fa5] 并打勾 ...
 - android: adapter getView(position==0) was invoked many times.
			
this is a big problem for me. i follow the solutions that i searched from the internet: modify the ...
 - hdu1251在词典里统计前缀出现的个数
			
banana band bee absolute acm ba b band abc #include<iostream> using namespace std; //数据结构 s ...
 - 十分钟理解Gradle
			
一.什么是Gradle 简单的说,Gradle是一个构建工具,它是用来帮助我们构建app的,构建包括编译.打包等过程.我们可以为Gradle指定构建规则,然后它就会根据我们的“命令”自动为我们构建ap ...
 - ASP.NET MVC 的自定义模型属性别名绑定
			
最近在研究 ASP.NET MVC 模型绑定,发现 DefaultModelBinder 有一个弊端,就是无法实现对浏览器请求参数的自定义,最初的想法是想为实体模型的属性设置特性(Attribute) ...
 - 给animator动态添加事件
			
using UnityEngine; using System.Collections; public class setAnimationEvent : MonoBehaviour { public ...