消息延迟是异步吗

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了消息延迟是异步吗相关的知识,希望对你有一定的参考价值。

消息延迟不是异步,消息延迟的具体情形包括:
一、网络延迟
这是经常的事件,我们所处的位置网络不好,或者运营商给我们短了网,或者是WiFi信号问题等等,都可能导致微信消息延迟,这是因为网络导致的延迟。
解决方式:建议大家在手机设置中,通过对无线和网络进行设置,保证即使在休眠状态下保持WLAN连接,或者始终连接数据业务,打开开关。
二、手机设置问题
我们以华为手机为例,我们要确保手机有没有被列入白名单,或者在电池自动启动中,有没有关闭。
三、通知栏的设置
比如我们将手机的通知功能关闭了,一样也收不到消息,需要进入手机“设置”,找到“通知栏和状态栏”,点击“通知管理”,将“允许通知”开启就好了;或者iPhone的设置——通知——允许通知打开。
手机省电模式下,可能也会将微信通知功能关闭,建议在不必要的时候开启省电模式。
参考技术A 废话补不多说上代码:

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

//发送消息
$redis->lPush($list, $value);

//消费消息
while (true)
try
$msg = $redis->rPop($list);
if (!$msg)
sleep(1);

//业务处理

catch (Exception $e)
echo $e->getMessage();


上面代码会有个问题如果队列长时间是空的,那pop就不会不断的循环,这样会导致redis的QPS升高,影响性能。所以我们使用sleep来解决,当没有消息的时候阻塞一段时间。但其实这样还会带来另一个问题,就是sleep会导致消息的处理延迟增加。这个问题我们可以通过blpop/brpop 来阻塞读取队列。

blpop/brpop在队列没有数据的时候,会立即进入休眠状态,一旦数据到来,则立刻醒过来。消息的延迟几乎为零。用blpop/brpop替代前面的lpop/rpop,就完美解决了上面的问题。

还有一个需要注意的点是我们需要是用try/catch来进行异常捕获,如果一直阻塞在那里,Redis服务器一般会主动断开掉空链接,来减少闲置资源的占用。

延迟队列
你是否在做电商项目的时候会遇到如下场景: - 订单下单后超过一小时用户未支付,需要关闭订单 - 订单的评论如果7天未评价,系统需要自动产生一条评论

这个时候我们就需要用到延时队列了,顾名思义就是需要延迟一段时间后执行。Redis可通过zset来实现。我们可以将有序集合的value设置为我们的消息任务,把value的score设置为消息的到期时间,然后轮询获取有序集合的中的到期消息进行处理。

实现代码如下:

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$redis->zAdd($delayQueue,$tts, $value);

while(true)
try
$msg = $redis->zRangeByScore($delayQueue,0,time(),0,1);
if($msg)
continue;

//删除消息
$ok = $redis.zrem($delayQueue,$msg);
if($ok)
//业务处理

catch(Exception $e)


消息队列介绍

应用解耦、异步通信、流量削峰、数据同步

功能
  • 优先级队列

    优先级高的消息优先被消费,如果消费者的消费速度大于生产者的速度,并且消息服务器中没有消息堆积,那么对发送的消息设置优先级也就没有意义了

  • 延迟队列

    延迟消息是指消息发送后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到消息进行消费

    延迟队列分两种:基于消息的延迟和基于队列的延迟,基于消息的延迟是指为每条消息设置不同的延迟时间,每当队列红油新消息进入就会重现根据延迟时间重新排序,这种方式的队列对性能影响很大;基于队列的延迟,是指不同延迟时间的消息放入不同的队列,每一个队列中的消息的延迟时间都是相同的,就不需要根据延迟时间进行排序了

  • 死信队列

    由于某些原因消息无法被正确的投递,为了确保消息不会无故丢弃,一般将其放入死信队列

    与此对应的是回退队列,试想如果消费者在消费时发生异常,那么就不会对消息进行确认(ack),进而发生回滚消息的操作之后消息始终放在队列的顶部,然后不断被处理和回滚,导致队列进入死循环,为了解决该问题,可以为每个队列设置一个回退队列,它和死信队列都是为异常的处理提供的一种机制保障,实际情况下,回退队列的角色可以由死信队列和重试队列来扮演。

  • 重试队列

    重试队列其实可以看成是一种回退队列,指当消费端消费消息失败时,为防止消息无故丢失而重新将消息回滚到broker中,与回退队列不同的是重试队列一般分为多个重试等级,每个重试等级一般也会设置重新投递延时,重试次数越多投递延时就越大。举个例子:消费第一次消息失败放入重试队列Q1,Q1的重新投递延迟为5S,在5s过后重新投递该消息,如果消息再次消费失败则入重试队列Q2,Q2的重新投递延迟为10S,在10s过后重新投递该消息;以此类推,重试越多次重新投递的时间就越久,为此需要设置一个上限,超过投递次数就进入死信队列

    重试队列与延迟队列的区别:延迟队列动作由内部触发,重试队列动作由外部消费端触发;延迟队列作用一次,而重试队列的动作范围会向后传递

  • 消费模式

    消费模式分为推模式和拉模式

  • 广播消息

    消息一般有两种传递模式:点对点模式和发布/订阅模式

  • 消息回溯

  • 消息堆积、持久化

    流量削峰得益于消息堆积的能力,消息堆积分为内存式堆积和磁盘式堆积

  • 消息追踪

  • 消息过滤

  • 多租户

  • 多协议支持

  • 跨语言支持

  • 流量控制

  • 消息顺序性

  • 安全机制

  • 消息幂等性

    例如:以订单号作为唯一性标识别,并在下游设置去重表

  • 事物性消息

性能

吞吐量、时延,消息堆积越大也就意味着时延也就越长,如果要求时效性高完全可以采用rpc方式实现。

可靠性、可用性

可靠性是指对消息不丢失的保障程度;可用性是指无故障运行的时间百分比

运维能力
社区力度及生态发展


以上是关于消息延迟是异步吗的主要内容,如果未能解决你的问题,请参考以下文章

消息队列介绍

Azure 服务总线可以在重试消息之前延迟吗?

golang实现本地延迟队列

消息队列(MQ)消息延迟及过滤设计方案

GCM 会在短时间内发送复制主题消息,而 gcm 会延迟发送吗?

MDB 消息消费者延迟