首页 > PHP教程 > php开发知识文章

php redis实现对百万用户的即时推送

怎么实现对百万用户的即时推送,这个推送一般为调用第三方的接口,push,邮件之类的东西。

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。

这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。

与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步

这里使用基于redis+php多进程的方案

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

redis集群

实现的具体代码:

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

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

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

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

//push推送配置 注:使用前请确认log文件为空
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 ="************ 请确认信息是否有误 * 10秒后启动push任务! *************
* 文件名称 : {$config['file']};
* 推送标题 : {$config['Title']};
* 推送内容 : {$config['Content']};
* 是否跳转 : {$config['OpenType']};
* 进程数量 : $num;(如果为单进程无视此项)
* 睡眠时间 : {$config['s']};
* 日志目录 : /log;
***************************************************************/n";
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);
}

以上就是本文php redis实现对百万用户的即时推送的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

关闭
感谢您的支持,我会继续努力!
扫码打赏,建议金额1-10元


提醒:打赏金额将直接进入对方账号,无法退款,请您谨慎操作。