简单使用php+redis实现消息队列推送
版权声明:
本文为博主原创文章,转载请声明原文链接...谢谢。o_0。
更新时间:
2019-12-03 11:36:05
温馨提示:
学无止境,技术类文章有它的时效性,请留意文章更新时间,如发现内容有误请留言指出,防止别人"踩坑",我会及时更新文章
前言
如果想用redis实现,订单队列等关键性东西,建议不要用redis。因为持久化,可靠性,不够。即使你能做到,也会很“吃力”。建议用RabbitMQ,redis实现的队列一般用于统计播放量、搜索热度、点击率、访客数量记录、等准备率不需要太高的场景。
实现原理
消息推送实现方法php+redis,压入一个消息,然后服务器自动提取出来发送出去,redis有个列表结构可以实现这个功能,重要的是它有个方法可以从列表中取数据,这个方法可以设置阻塞(超时)获取,如果列表中没有消息则可以等待,实现代码如下
压入消息
$redis = new redis();
$redis->connect('127.0.0.1', 6379) or die('connect error!');
$redis->select(8);
$redis->lpush('msglist', rand(1000, 9999));服务器取出并通知
ini_set('default_socket_timeout', -1);
$redis = new redis();
$redis->pconnect('127.0.0.1', 6379) or die('connect error!');
$redis->select(8);
while (true) {
//等100秒
var_dump($redis->blpop('msglist', 100));
}注意上面服务器连接用的是长链接,并且设置啦socket的超时时间为永不超时,效果如下

使用enqueue/redis实现
安装
有轮子用当然直接用喽,安装enqueue/redis,文档地址 https://php-enqueue.github.io/transport/redis/
composer require enqueue/redis
创建上下文
连接redis并且创建一个上下文件对象
use Enqueue\Redis\RedisConnectionFactory; //包含自动加载类 $loader = require __DIR__ . '/../vendor/autoload.php'; $factory = new RedisConnectionFactory([ 'host' => '127.0.0.1', 'port' => 6379, 'scheme_extensions' => ['phpredis'], ]); $context = $factory->createContext();
生产消息
$fooQueue = $context->createQueue('redismq:aQueue');
$message = $context->createMessage('Hello world!');
$context->createProducer()->send($fooQueue, $message);生产一个定时过期消息
下面消息60后会自动从队列中删除
$message = $context->createMessage('Hello world!');
$context->createProducer()
->setTimeToLive(60000) // 60 sec
->send($fooQueue, $message);生产一个延期消息
5秒之后消息能会被加入队列
$message = $context->createMessage('Hello world!');
$context->createProducer()
->setDeliveryDelay(5000) // 5 sec
->send($fooQueue, $message);消费消息
$fooQueue = $context->createQueue('redismq:aQueue');
$consumer = $context->createConsumer($fooQueue);
while (true) {
//接收消息 默认是5000毫秒超时,这个地方的超时会影响延期消息的处理不能设置太大,请注意下
$message = $consumer->receive();
if ($message) {
$body = $message->getBody();
echo $body;
//...业务处理
// 确认消费并删除消息,如果不执行下面则此条消息会被标识为已经接收,但并不会删除
$consumer->acknowledge($message);
//$consumer->reject($message);
}
}删除队列(清空消息)
$context->deleteQueue($fooQueue);
redis保存的数据结构如下
