php redis实现对200w用户的即时推送


Posted in PHP onMarch 04, 2017

怎么实现对200w用户的即时推送,这个推送可以理解为调用第三方的接口,push,sms之类的东西。

当时先写了一个demo 直接读取DB然后单个推送,结果。。可想而知

于是设计一套基于redis+php多进程的方案,用着还不错而去扩展性蛮高的,故分享之。

=============================================

具体的逻辑如下:(无视我的字体)

php redis实现对200w用户的即时推送

其实这里还可以优化的,我的设想是如果用户数据再多一些的话,可以在redis里对数据进行分割采取多List,每一个List对应多个php进程这样会更快。

下面是我实现的具体代码:

主管理脚本:应用时启动这个即可。 

<?php     //push推送配置 注:使用前请确认log文件为空    2016-04-12 
include_once(dirname (__FILE__)."/../../config.inc.php"); 
//if(exec('ps aux | grep redis_push.php | grep -v grep | wc -l') != 0) goto check; 
import('push.class.php'); 
import('Redis.class.php'); 
 
$time =time(); 
$data = array("apikey"=>'xxxx',"secret"=>'xxxx'); 
$push = new Channel($data); 
$redis = new RedisCache($Credis['host'],$Credis['port']); 
if(exec('ps aux | grep redis_push.php | grep -v grep | wc -l') != 0) goto check;//如果有推送任务 直接执行监控代码 
 
/*PUSH配置项*/ 
$config = array( 
 "file"=>"test.txt", 
 "Title"=>"sssss", 
 "Content"=>"ssssssssssssssss", 
 "OpenType"=>"0",  //1是 0否  是否跳转链接 
 "Url"=>"",     //链接地址 
 "num"=>"500",   //每次推送条数 
 "s"=>"1"      //睡眠时间 (单位:秒) 
); 
$num = 15;      //启动进程数量 
$a = $config['OpenType']==1 ? "是" : "否"; 
$c = json_encode($config); 
$info = <<<monkey 
  ************ 请确认信息是否有误*10秒后启动push任务! ************* 
  * 文件名称  : {$config['file']}; 
  * 推送标题  : {$config['Title']}; 
  * 推送内容  : {$config['Content']}; 
  * 是否跳转  : {$config['OpenType']}; 
  * 进程数量  : $num;(如果为单进程无视此项) 
  * 睡眠时间  : {$config['s']}; 
  * 日志目录  : /log; 
  ***************************************************************\n 
monkey; 
echo $info; 
sleep(3); 
$n = 1; 
while($n<=10){ 
 echo (10-$n++),"秒\n"; 
 sleep(1); 
} 
echo "------------------------- 任务已启动 -------------------------\n"; 
if($redis->Scount('push_getchannel_success')){ 
 echo "队列有未完成任务\n"; 
}else{ 
 $res = exec("php redis_getchannel.php {$config['file']}");//写入redis脚本 
 echo $res; 
} 
smtp_mail('xxxx@qq.com','推送任务已开启','请实时监测,5秒后您的手机将接收到测试推送!');//推送监控 实现定时全自动推送  
echo "\n---------------- 5秒后 test 将收到测试推送消息 ----------------\n"; 
sleep(5); 
$re = $push->BaiduPush('xxxx','xxxxx',$config['Content'],$config['Title'],'1',$config['OpenType'],$config['Url'],'xxxxx',$push); 
sleep(1); 
echo "\n---------------- 测试推送已发出!如未收到,请及时终止程序! 10秒后正式推送!!! ----------------\n"; 
$m = 1; 
while($m<=10){ 
 echo (10-$m++),"秒\n"; 
 sleep(1); 
} 
echo "\n---------------- 推送任务已经开始!请耐心等待! ----------------\n"; 
//下面设置是否多进程 
for($i=1;$i<=$num;$i++){ 
exec("php redis_push.php '{$c}' > /dev/null 2>&1 &"); 
} 
 
check: 
while(1){ 
 if(exec('ps aux | grep redis_push.php | grep -v grep | wc -l') == 0){ 
  echo "push 发送完成 用时",time()-$time,"秒"; 
  die(); 
 } 
 echo "当前进程数:",exec('ps aux | grep redis_push.php | grep -v grep | wc -l'),"个","\n"; 
 echo "当前剩余推送数量:".$redis->Scount('push_getchannel_success')."\n"; 
 sleep(10); 
}

至于写入redis和具体的推送脚本这个靠自己的想象里就好了 我就不发了 嘿嘿

我的做法是具体的推送脚本在推送一定数量后会自动终止并调用自己本身。

因为在实际应用中发现php脚本在长时间运行之后会发生假死(可能是因为上下文切换的问题),所以我都是避免让php脚本长时间运行。

还有就是用户肯定不是固定的200w用户 每天都会有一个增量,我的方案是通过定时脚本每天把增量的用户整理进我自己设计的一个用户表自己管理。

ps:我把所有的脚本弄到了一个我自己整理的小的php原生框架统一管理,过段时间我发出来。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
消息持续发送的完整例子
Oct 09 PHP
PHP编程过程中需要了解的this,self,parent的区别
Dec 30 PHP
php设计模式 Delegation(委托模式)
Jun 26 PHP
Yii开启片段缓存的方法
Mar 28 PHP
php时间函数用法分析
May 28 PHP
总结PHP中数值计算的注意事项
Aug 14 PHP
PHP设置images目录不充许http访问的方法
Nov 01 PHP
PHP编程实现微信企业向用户付款的方法示例
Jul 26 PHP
php使用curl_init()和curl_multi_init()多线程的速度比较详解
Aug 15 PHP
PHP实现的pdo连接数据库并插入数据功能简单示例
Mar 30 PHP
浅谈laravel orm 中的一对多关系 hasMany
Oct 21 PHP
php 多继承的几种常见实现方法示例
Nov 18 PHP
php获取目录中所有文件名及判断文件与目录的简单方法
Mar 04 #PHP
PHP redis实现超迷你全文检索
Mar 04 #PHP
浅谈php中变量的数据类型判断函数
Mar 04 #PHP
PHP检测数据类型的几种方法(总结)
Mar 04 #PHP
php redis实现文章发布系统(用户投票系统)
Mar 04 #PHP
PHP获取当前执行php文件名的代码
Mar 02 #PHP
PHP两种实现无级递归分类的方法
Mar 02 #PHP
You might like
Yii框架关联查询with用法分析
2014/12/02 PHP
PHP版本常用的排序算法汇总
2015/12/20 PHP
Zend Framework教程之Bootstrap类用法概述
2016/03/14 PHP
Jquery Ajax请求代码(2)
2011/01/07 Javascript
将json当数据库一样操作的javascript lib
2013/10/28 Javascript
JQuery validate插件Remote用法大全
2016/05/15 Javascript
第一次接触神奇的Bootstrap基础排版
2016/07/26 Javascript
Vue.js组件tree实现无限级树形菜单
2016/12/02 Javascript
bootstrapValidator表单验证插件学习
2016/12/30 Javascript
vue.js数据绑定的方法(单向、双向和一次性绑定)
2017/07/13 Javascript
vue 利用路由守卫判断是否登录的方法
2018/09/29 Javascript
vue的keep-alive用法技巧
2019/08/15 Javascript
vue element-ui中table合计指定列求和实例
2020/11/02 Javascript
Python作用域用法实例详解
2016/03/15 Python
Python语言实现百度语音识别API的使用实例
2017/12/13 Python
查看django执行的sql语句及消耗时间的两种方法
2018/05/29 Python
python中cPickle类使用方法详解
2018/08/27 Python
Python判断变量名是否合法的方法示例
2019/01/28 Python
python3.7简单的爬虫实例详解
2019/07/08 Python
Python响应对象text属性乱码解决方案
2020/03/31 Python
tensorflow之读取jpg图像长和宽实例
2020/06/18 Python
Python如何读写CSV文件
2020/08/13 Python
详解解决jupyter不能使用pytorch的问题
2021/02/18 Python
Nordgreen台湾官网:极简北欧设计手表
2019/08/21 全球购物
C#如何调用Word并打开一个Word文档
2013/05/08 面试题
最新的大学生找工作自我评价
2013/09/29 职场文书
护理职业应聘自荐书
2013/09/29 职场文书
大学生职业生涯规划书范文
2014/01/04 职场文书
单位领导证婚词
2014/01/14 职场文书
文科生自我鉴定
2014/02/15 职场文书
不会写演讲稿,快来看看这篇文章!
2019/08/06 职场文书
MySQL InnoDB ReplicaSet(副本集)简单介绍
2021/04/24 MySQL
MySQL系列之十二 备份与恢复
2021/07/02 MySQL
分享几个简单MySQL优化小妙招
2022/03/31 MySQL
教你在 Java 中实现 Dijkstra 最短路算法的方法
2022/04/08 Java/Android
Oracle删除归档日志及添加定时任务
2022/06/28 Oracle