PHP+redis实现微博的拉模型案例详解


Posted in PHP onJuly 10, 2019

本文实例讲述了PHP+redis实现微博的拉模型。分享给大家供大家参考,具体如下:

上回写了一篇推模型的内容,这回分享一篇拉模型的内容。

拉模型

拉模型就是展示微博的时候,获取自己的所有关注的人,然后从关注的人中拉取最新微博。

微博项目数据结构设计

user表设计

注册的时候将user数据写入redis中,key如下:

user数据的key
用户名=user:uesrid:$uesrid:username
密码=user:userid:$userid:password

还需要这样写一份,因为需要靠用户名来登录,这样就可以根据用户名来查询用户id。

user:username:userid:$userid

关注的人和粉丝设计

每个用户在产生关注的动作后,在redis中维护两个无序集合set,一个是following,一个是follower,following集合保存的是我关注的人,follower集合保存的是我的粉丝。注意是每个用户都要维护这样的两个集合,用userid来区别。

单条微博表设计

每条微博的信息用hash结构来存储,根据不同的微博id来区分,每条微博有如下信息:发布人id,发布人昵称,发布时间,微博内容。

拉取关注者微博表 设计

每个用户发布微博后,维护20条最新微博,并保存到有序集合sorted set中,用不同的userid来区分。

注意:有序集合的score用微博id,集合保存的也是微博id。

个人微博表

每个用户维护自己的微博,保存到链表中,只保存1000条,redis中只保存1000条微博数据,如果想查询更多,去数据库中查询。

个人已拉取表设计

每个用户在拉取微博后,将微博保存到已经拉取的表中,这个表是一个链表结构,最多保存1000条微博。

发布微博

首先将微博保存成hash结构,然后将微博保存到拉取表,还保存到个人微博表。

//1、保存微博
$conn = connredis();
$postid = $conn->incr('global:postid');
$conn->hmset('post:postid:'.$postid,['userid'=>$user['userid'],'username'=>$user['username'],'time'=>time(),'content'=>$content]);
//2、每个人维护20条最新微博,保存到有序集合中
$conn->zadd('starpost:userid:'.$user['userid'],$postid,$postid);
if($conn->zcard('starpost:userid:'.$user['userid']) > 20){
  $conn->zremrangebyrank('starpost:userid:'.$user['userid'],0,0);
}
//3、维护个人的1000条微博,保存到链表中
$conn->lpush('mypost:userid:'.$user['userid'],$postid);
if($conn->llen('mypost:userid:'.$user['userid']) > 1000){
  $conn->rpoplpush('mypost:userid:'.$user['userid'],'global:post');
}

展示微博

首先获取所有关注的人,获取上次拉取微博的位置,根据上次拉取的微博位置来拉取数据。然后给微博排序,设置新的拉取的位置,写入到已拉取表中,获取微博的详细内容,最后获取粉丝和关注数。进行展示即可。

//1、获取拉取对象
$stars = $conn->smembers('following:'.$user['userid']);//获取所有关注的人
$stars[] = $user['userid'];//需要拉取自己的微博
//2、获取上次拉取的位置
$lastpull = $conn->get('lastpull:userid:'.$user['userid']);
if(!$lastpull){
$lastpull = 0;
}
//3、拉取微博 
$latest = [];
foreach($stars as $star){
$latest = array_merge($latest,$conn->zrangebyscore('starpost:userid:'.$star,$lastpull+1,1<<32-1));
}
//4、给微博排序
sort($latest,SORT_NUMERIC);
//5、设置拉取的位置
if(!empty($latest)){
  $conn->set('lastpull:userid:'.$user['userid'],end($latest));
}
//6、写入到已拉取表中
foreach($latest as $l){
  $conn->lpush('receivepost:'.$user['userid'],$l);
}
$conn->ltrim('receivepost:'.$user['userid'],0,999);//至多显示1000条微博
//7、获取微博的详细内容
$postids = $conn->sort('receivepost:'.$user['userid'],['sort'=>'desc']);
$posts = [];
foreach($postids as $postid){
  $posts[] = $conn->hmget('post:postid:'.$postid,['userid','username','time','content']);
}
//8、获取粉丝和关注数
$fansnum = $conn->scard('follower:'.$user['userid']);
$follownum = $conn->scard('following:'.$user['userid']);

Q&A

如何保证拉取的数据时最新的?

在拉取的时候,将最近拉取的微博id保存到redis中,然后下次我们只需要去拉取比这次保存的微博id大的微博,就可以保证拉取的数据是之前没有拉取的。

如何拉取所有关注者的数据?

遍历关注者,然后拉取数据

假设拉取A关注者的微博1,4,5 B关注者2,3,但是他们的发布时间交错,怎么展示数据?

将所有关注者的最新微博都取出来,然后根据微博id进行排序。

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
判断是否为指定长度内字符串的php函数
Feb 16 PHP
php URL验证正则表达式
Jul 19 PHP
PHP5权威编程阅读学习笔记 附电子书下载
Jul 05 PHP
php+xml编程之SimpleXML的应用实例
Jan 24 PHP
浅谈php自定义错误日志
Feb 13 PHP
浅谈PHP接收POST数据方式
Jun 05 PHP
php使用pclzip类实现文件压缩的方法(附pclzip类下载地址)
Apr 30 PHP
PHP简单数据库操作类实例【支持增删改查及链式操作】
Oct 10 PHP
PHP面向对象程序设计子类扩展父类(子类重新载入父类)操作详解
Jun 14 PHP
tp5.1 实现setInc字段自动加1
Oct 18 PHP
php设计模式之备忘模式分析【星际争霸游戏案例】
Mar 24 PHP
详解php中流行的rpc框架
May 29 PHP
php解压缩zip和rar压缩包文件的方法
Jul 10 #PHP
PHP+redis实现微博的推模型案例分析
Jul 10 #PHP
实例分析10个PHP常见安全问题
Jul 09 #PHP
PHP批斗大会之缺失的异常详解
Jul 09 #PHP
PHP结合Redis+MySQL实现冷热数据交换应用案例详解
Jul 09 #PHP
PHP+Redis开发的书签案例实战详解
Jul 09 #PHP
使用composer命令加载vendor中的第三方类库 的方法
Jul 09 #PHP
You might like
php UTF-8、Unicode和BOM问题
2010/05/18 PHP
snoopy 强大的PHP采集类使用实例代码
2010/12/09 PHP
在WordPress中实现发送http请求的相关函数解析
2015/12/29 PHP
全面了解PHP中的全局变量
2016/06/17 PHP
总结PHP中数值计算的注意事项
2016/08/14 PHP
php+redis实现多台服务器内网存储session并读取示例
2017/01/12 PHP
thinkphp整合系列之极验滑动验证码geetest功能
2019/06/18 PHP
Laravel框架查询构造器 CURD操作示例
2019/09/04 PHP
yii2.0框架使用 beforeAction 防非法登陆的方法分析
2019/09/11 PHP
laravel中的fillable和guarded属性详解
2019/10/23 PHP
html读出文本文件内容
2007/01/22 Javascript
javascript之锁定表格栏位
2007/06/29 Javascript
在JavaScript的jQuery库中操作AJAX的方法讲解
2015/08/15 Javascript
AngularJS自定义指令详解(有分页插件代码)
2017/06/12 Javascript
纯JS实现可用于页码更换的飞页特效示例
2018/05/21 Javascript
搭建一个nodejs脚手架的方法步骤
2019/06/28 NodeJs
详解Vue的watch中的immediate与watch是什么意思
2019/12/30 Javascript
js中!和!!的区别与用法
2020/05/09 Javascript
js实现扫雷源代码
2020/11/27 Javascript
[50:01]Ti4 冒泡赛第二天 NEWBEE vs Titan
2014/07/15 DOTA
[03:24]CDEC.Y赛前采访 努力备战2016国际邀请赛中国区预选赛
2016/06/25 DOTA
python利用urllib和urllib2访问http的GET/POST详解
2017/09/27 Python
便捷提取python导入包的属性方法
2018/10/15 Python
对numpy下的轴交换transpose和swapaxes的示例解读
2019/06/26 Python
用Anaconda安装本地python包的方法及路径问题(图文)
2019/07/16 Python
python3操作注册表的方法(Url protocol)
2020/02/05 Python
基于Python采集爬取微信公众号历史数据
2020/11/27 Python
Python爬虫之Selenium库的使用方法
2021/01/03 Python
Numpy ndarray 多维数组对象的使用
2021/02/10 Python
九州传奇上机题
2014/07/10 面试题
自荐信格式的六要素
2013/09/21 职场文书
客户代表自我评价范例
2013/09/24 职场文书
学生会干部自荐信
2014/02/04 职场文书
xxx同志考察材料
2014/02/07 职场文书
2014年人力资源部工作总结
2014/11/19 职场文书
2015年读书月活动总结
2015/03/26 职场文书