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

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介:

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


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
74 6
|
16天前
|
存储 NoSQL PHP
PHP与Redis结合使用,提升数据存储性能
随着互联网应用的发展,PHP与Redis的结合成为提升数据存储性能的重要手段。PHP作为流行的服务器端语言,常用于网站开发;Redis作为高性能内存数据库,以其快速读写能力,有效优化数据访问速度,减轻数据库压力。两者结合通过缓存机制显著提升应用响应速度,支持高并发场景下的稳定性和可扩展性。
|
17天前
|
JavaScript PHP 数据安全/隐私保护
乞丐在线要饭系统PHP网站源码
在这个物欲横流、竞争激烈的时代,有时候我们真心觉得钱来得太不容易,甚至连最基本的生存都成了负担。于是,我们想出了一个特别“独特”的点子:用利息砸我,给我点施舍!
41 1
|
23天前
|
存储 NoSQL 关系型数据库
PHP 使用 Redis
10月更文挑战第22天
23 6
ly~
|
1月前
|
存储 安全 前端开发
php文件管理系统
PHP 文件管理系统是基于 PHP 开发的,用于管理文件和文件夹的应用。它支持文件上传、下载、浏览、搜索、编辑和删除,并提供权限管理和安全防护功能。适用于企业内部、网站和个人文件管理,确保文件的安全性、保密性和高效共享。
ly~
29 9
ly~
|
1月前
|
存储 自然语言处理 前端开发
有哪些常见的 PHP 文件管理系统?
elFinder:开源Web文件管理器,支持文件的基本操作及拖放管理,具备多种文件预览、权限管理功能,适用于网站后台文件管理和共享主机环境。 FileRun:多语言、易用的文件管理工具,提供强大的搜索和版本控制功能,支持外部存储集成,适用于企业内部文件共享与协作。 KCFinder:轻量级PHP文件管理器,易于集成,支持文件上传下载限制,与富文本编辑器兼容,适用于博客系统和内容编辑场景。 AjaXplorer:基于Ajax技术的文件管理系统,提供流畅体验和插件扩展,支持文件分类和共享,适用于团队协作和灵活文件分享场景。
ly~
47 1
|
16天前
|
JavaScript NoSQL Java
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
31 0
|
1月前
|
前端开发 JavaScript 小程序
前端uni开发后端用PHP的圈子系统该 如何做源码?
圈子系统系统基于TP6+Uni-app框架开发;客户移动端采用uni-app开发,管理后台TH6开发。系统支持微信公众号端、微信小程序端、H5端、PC端多端账号同步,可快速打包生成APP
|
1月前
|
前端开发 JavaScript PHP
Thinkphp在线客服系统源码多语言外贸版_PHP客服系统源码Uniapp开发搭建+论文设计
Thinkphp在线客服系统源码多语言外贸版_PHP客服系统源码Uniapp开发搭建+论文设计
|
1月前
|
缓存 NoSQL 数据处理
原生php实现redis缓存配置和使用方法
通过上述步骤,你可以在PHP项目中配置并使用Redis作为高性能的缓存解决方案。合理利用Redis的各种数据结构和特性,可以有效提升应用的响应速度和数据处理效率。记得在实际应用中根据具体需求选择合适的缓存策略,如设置合理的过期时间,以避免内存过度消耗。
52 0