Redis如何实现消息队列

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/William0318/article/details/89285965

消息队列的实现方式有很多种,比如有专业的rabbitmq,rocketmq,kafka等,这些mq提供了非常专业的功能实现异步发送,而且这些接入又比较复杂。

Redis 利用 其 专有的数据结构list可以实现简单的消息队列和异步发送的需求,当然可专业的mq相比,在消息投递的可靠性和及时性上还是有差距,如果对异步发送要求比较高,则建议还是采用专业的mq中间件。

Redis如何实现消息队列

Redis的list可以用来实现消息队列,key用来表示队列名称,客户端向对应的key代表的队列发消息。发消息采用rpush,lpush实现,取消息采用rpop或lpop实现。

consumer端最好也是多个线程,防止一个线程崩溃或发生异常,队列消息积压的情况。

队列空了,利用pop这样会使Redis空轮询,浪费资源,此时可以让线程sleep一会儿再去取,可以明显的降低redis的负载。导致的问题是1s的消息延迟,这对于异步处理来说,已经很大了。

Redis提供了blpop和brpop可以进行阻塞读,没有消息的时候进行阻塞操作。
如果队列长时间没有消息,一直进行阻塞连接,redis会对空闲连接进行释放以减少资源浪费,所以必须对异常进行捕获重试。

Redis实现消息队列php代码

//消费端
public function consumerMsg($queueName){
  try{
      $value = $this->redis->brpop($queueName);
      do_callback($value);
  }catch(Exception $e){
      log($queueName, $e->getMessage());
      delayedRetryMsg($queueName); //发生异常,延迟重试
  }
}
//发布端
public function publishMsg($queueName, $msg){
   try{
       $this->redis->lpush($queueName, $msg);
   }catch(Exception $e){
       log($queueName, $e->getMessage());
       $this->redis->lpush($queueName, $msg);//发生异常重试
   }
}

Redis如何实现延时队列

redis延时队列功能可以采用zset进行处理,将消息序列化为value,执行时间作为score,按照当前时间作为范围去取该执行的消息进行处理。处理线程建议是多个,防止一个线程发生异常导致整个队列不可用。

public function publishMsgToDelayQueue($queueKey, $msg){
     $this->redis->zadd($queueKey, time() + 5, $msg);//5s延迟队列
}

staitc $isOn = true;
public function getMsgFromQueue($queueKey){
    while($isOn){
     $values = $this->redis->zrangebyscore($queueKey, 0, time()); //取出当前时间执行的所有消息
     try {
        if(false == empty($values)){
         foreach($values as $msg){
            if($this->redis->zrem(queueKey, s) > 0)){
                do_handle($msg);
            }
          }
        }else{
          sleep(1);
        }
     }catch(Exception $e){
       $isOn = false;   
}
}


猜你喜欢

转载自blog.csdn.net/William0318/article/details/89285965