很多站长朋友们都不太清楚phpredis列队,今天小编就来给大家整理phpredis列队,希望对各位有所帮助,具体内容如下:
本文目录一览: 1、 如何使用Redis 做队列操作 2、 redis队列什么意思 3、 php redis 队列 会出现并发问题吗 4、 php 后台怎么开一个进程监听Redis的队列消息呢?用while 5、 php使用redis的有序集合zset实现延迟队列 6、 消息队列为什么用redis实现 如何使用Redis 做队列操作redis设计用来做缓存的,但是由于它自身的某种特性使得它可以用来做消息队列,它有几个阻塞式的API可以使用,正是这些阻塞式的API让其有能力做消息队列;
另外,做消息队列的其他特性例如FIFO(先入先出)也很容易实现,只需要一个list对象从头取数据,从尾部塞数据即可;
redis能做消息队列还得益于其list对象blpop brpop接口以及Pub/Sub(发布/订阅)的某些接口,它们都是阻塞版的,所以可以用来做消息队列。
redis队列什么意思Redis队列功能介绍
List
常用命令:
Blpop删除,并获得该列表中的第一元素,或阻塞,直到有一个可用
Brpop删除,并获得该列表中的最后一个元素,或阻塞,直到有一个可用
Brpoplpush
Lindex获取一个元素,通过其索引列表
Linsert在列表中的另一个元素之前或之后插入一个元素
Llen获得队列(List)的长度
Lpop从队列的左边出队一个元素
Lpush从队列的左边入队一个或多个元素
Lpushx当队列存在时,从队到左边入队一个元素
Lrange从列表中获取指定返回的元素
Lrem从列表中删除元素
Lset设置队列里面一个元素的值
Ltrim修剪到指定范围内的清单
Rpop从队列的右边出队一个元素
Rpoplpush删除列表中的最后一个元素,将其追加到另一个列表
Rpush从队列的右边入队一个元素
Rpushx从队列的右边入队一个元素,仅队列存在时有效
Redis支持php、python、c等接口
应用场景:
Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现。
Lists 就是链表,相信略有数据结构知识的人都应该能理解其结构。使用Lists结构,我们可以轻松地实现最新消息排行等功能。
Lists的另一个应用就是消息队列,
可以利用Lists的PUSH操作,将任务存在Lists中,然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作Lists中某一段的api,你可以直接查询,删除Lists中某一段的元素。
如果需要还可以用redis的Sorted-Sets数据结构来做优先队列.可以给每条消息加上一个唯一的序号。这里就不详细介绍了。
实现方式:
Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。
示意图:
1)入队
2)出队(非阻塞模式)
lpop弹出列表首元素(即最后入队的元素)
Rpop弹出列表尾元素 (即入队的最开始的一个元素)
注意:如果要当作队列功能,应该是用这个出队
这里的出队都是非阻塞模式,就是你用pop出队的时候,如果队列是空的话,你得到的是一个NULL的值
3)出队(阻塞模式)
假如现在queue队列为空 我们用brpop命令
BRPOP 是一个阻塞的列表弹出原语。 它是 RPOP 的阻塞版本,因为这个命令会在给定list无法弹出任何元素的时候阻塞连接。 该命令会按照给出的 key 顺序查看 list,并在找到的第一个非空 list 的尾部弹出一个元素。
A)
我们执行brpop命令
可以看到队列queue没有元素的时候 是阻塞的 即不返回值
其中0是超时时间 为0表示一直等待
B)
这个时候我们用lpush往队列里 入队一个数据“bbb”
C)
阻塞的队列立马会弹出出队元素 显示队列名字 和 出队元素 已经等待了多少时间
D)
Brpop还能同时阻塞多个队列比如这样
用redis的list当作队列可能存在的问题
1)redis崩溃的时候队列功能失效
2)如果入队端一直在塞数据,而出队端没有消费数据,或者是入队的频率大而多,出队端的消费频率慢会导致内存暴涨
3)Redis的队列也可以像rabbitmq那样 即可以做消息的持久化,也可以不做消息的持久化。
当做持久话的时候,需要启动redis的dump数据的功能.暂时不建议开启持久化。
Redis其实只适合作为缓存,而不是数据库或是存储。它的持久化方式适用于救救急啥的,不太适合当作一个普通功能来用。应为dump时候,会影响性能,数据量小的时候还看不出来,当数据量达到百万级别,内存10g左右的时候,非常影响性能。
4)假如有多个消费者同时监听一个队列,其中一个出队了一个元素,另一个则获取不到该元素
5)Redis的队列应用场景是一对多或者一对一的关系,即有多个入队端,但是只有一个消费端(出队)
PHP的redis 简单操作示例
php redis 队列 会出现并发问题吗// 创建请求ID标志, uniqid 无法保证唯一, 自己去搜索生成唯一的方法
$uuid = uniqid();
$tsk_name = "mytask";
$time_out = 30000; // 超时策略: 30秒
$time_start = time();
$redis->rPush($tsk_name, $uuid); // 右(后)插入队列
// 堵塞等待队列中第一个和$uuid匹配的(到我了)
while($uuid != $redis->lGet($tsk_name, 0)){
if((time()-$time_start)> $time_out) {
break; // 超时跳出(某些原因队列异常了, 可能永远取不到)
}
usleep(10); // sleep 10ms, 再次尝试
}
// 这里执行任务的处理代码....
// $response 已拼装好要返回的内容
// 处理完成后(数据库等已入库更新), 需要:
if($redis->lGet($tsk_name, 0) == $uuid){ // 再次确认第一个是本请求
$redis->lPop($tsk_name); // 完成任务了, 从队列中移除
}else{
// 出现这种情况, 是因为超时了, 或前面的$uuid没有被消费
// 若不清除, 后续的请求, 都将无法正常进入队列执行
// 取队列中的所有$uuid
$queues = $redis->lRange($tsk_name, 0, -1);
foreach($queues as $i=>$uid){
if($uid==$uuid){
php 后台怎么开一个进程监听Redis的队列消息呢?用whileredis的subscribe用pconnect链接,执行这个脚本的进程会自动监听所订阅的频道发送的消息
ini_set(‘default_socket_timeout’, -1);
$redis = new \Redis();
$redis->pconnect('127.0.0.1', 6379);
//订阅
$redis->subscribe(['msg'], 'callfun');
function callfun($redis, $channel, $msg)
{
var_dump([
'redis' => $redis,
'channel' => $channel,
'msg' => $msg
]);
}
php使用redis的有序集合zset实现延迟队列延迟队列就是个带延迟功能的消息队列,相对于普通队列,它可以在指定时间消费掉消息。
我们通过redis的有序集合zset来实现简单的延迟队列,将消息数据序列化,作为zset的value,把消息处理时间作为score,每次通过zRangeByScore获取一条消息进行处理。
然后,我们写一个php脚本,用来处理队列中的任务。
消息队列为什么用redis实现redis只是提供一个高性能的、原子操作的分布式队列实现。具体的业务还是得需要你自己定制。
你的需求实际上是一个变形的生产者-消费者实现。对于此类需求,主要是将请求和实际的处理过程解耦,一般都是采取异步的方式来通知请求方,这跟用不用redis其实没有多大的关系。一般的实现方法是你需要将用户的请求封装成一个Task,然后将这个Task再push到redis队列,然后后端的worker.php完全可以多进程、多线程的并发处理Task并将处理结果回调给请求方。这里唯一麻烦点的就是这个Task的设计,需要能够包含请求信息(请求内容,请求方标识等等).
关于phpredis列队的介绍到此就结束了,不知道本篇文章是否对您有帮助呢?如果你还想了解更多此类信息,记得收藏关注本站,我们会不定期更新哦。
查看更多关于phpredis列队 php使用redis队列秒杀的详细内容...