基于Redis的MessageQueue队列封装

原创文章,转载请注明出处:http://www.huyanping.cn/?p=275
作者:Jenner

Redis的链表List可以用来做链表,高并发的特性非常适合做分布式的并行消息传递。

项目地址:https://github.com/huyanping/Zebra-PHP-Framework

左进右出

[php]  view plain  copy
  1. $redis->lPush($key$value);  
  2. $redis->rPop($key);  

 以下程序已在生产环境中正式使用。

基于Redis的PHP消息队列封装

[php]  view plain  copy
  1. <?php  
  2. /** 
  3.  * Created by PhpStorm. 
  4.  * User: huyanping 
  5.  * Date: 14-8-19 
  6.  * Time: 下午12:10 
  7.  * 
  8.  * 基于Redis的消息队列封装 
  9.  */  
  10. namespace Zebra\MessageQueue;  
  11.   
  12. class RedisMessageQueue implements IMessageQueue  
  13. {  
  14.   
  15.     protected $redis_server;  
  16.   
  17.     protected $server;  
  18.   
  19.     protected $port;  
  20.   
  21.     /** 
  22.      * @var 消息队列标志 
  23.      */  
  24.     protected $key;  
  25.   
  26.     /** 
  27.      * 构造队列,创建redis链接 
  28.      * @param $server_config 
  29.      * @param $key 
  30.      * @param bool $p_connect 
  31.      */  
  32.     public function __construct($server_config = array('IP' => '127.0.0.1''PORT' => '6379'), $key = 'redis_message_queue'$p_connect = false)  
  33.     {  
  34.         if (empty($key))  
  35.             throw new \Exception('message queue key can not be empty');  
  36.   
  37.         $this->server = $server_config['IP'];  
  38.         $this->port = $server_config['PORT'];  
  39.         $this->key = $key;  
  40.   
  41.         $this->check_environment();  
  42.         if ($p_connect) {  
  43.             $this->pconnect();  
  44.         } else {  
  45.             $this->connect();  
  46.         }  
  47.     }  
  48.   
  49.     /** 
  50.      * 析构函数,关闭redis链接,使用长连接时,最好主动调用关闭 
  51.      */  
  52.     public function __destruct()  
  53.     {  
  54.         $this->close();  
  55.     }  
  56.   
  57.     /** 
  58.      * 短连接 
  59.      */  
  60.     private function connect()  
  61.     {  
  62.         $this->redis_server = new \Redis();  
  63.         $this->redis_server->connect($this->server, $this->port);  
  64.     }  
  65.   
  66.     /** 
  67.      * 长连接 
  68.      */  
  69.     public function pconnect()  
  70.     {  
  71.         $this->redis_server = new \Redis();  
  72.         $this->redis_server->pconnect($this->server, $this->port);  
  73.     }  
  74.   
  75.     /** 
  76.      * 关闭链接 
  77.      */  
  78.     public function close()  
  79.     {  
  80.         $this->redis_server->close();  
  81.     }  
  82.   
  83.     /** 
  84.      * 向队列插入一条信息 
  85.      * @param $message 
  86.      * @return mixed 
  87.      */  
  88.     public function put($message)  
  89.     {  
  90.         return $this->redis_server->lPush($this->key, $message);  
  91.     }  
  92.   
  93.     /** 
  94.      * 向队列中插入一串信息 
  95.      * @param $message 
  96.      * @return mixed 
  97.      */  
  98.     public function puts(){  
  99.         $params = func_get_args();  
  100.         $message_array = array_merge(array($this->key), $params);  
  101.         return call_user_func_array(array($this->redis_server, 'lPush'), $message_array);  
  102.     }  
  103.   
  104.     /** 
  105.      * 从队列顶部获取一条记录 
  106.      * @return mixed 
  107.      */  
  108.     public function get()  
  109.     {  
  110.         return $this->redis_server->lPop($this->key);  
  111.     }  
  112.   
  113.     /** 
  114.      * 选择数据库,可以用于区分不同队列 
  115.      * @param $database 
  116.      */  
  117.     public function select($database)  
  118.     {  
  119.         $this->redis_server->select($database);  
  120.     }  
  121.   
  122.     /** 
  123.      * 获得队列状态,即目前队列中的消息数量 
  124.      * @return mixed 
  125.      */  
  126.     public function size()  
  127.     {  
  128.         return $this->redis_server->lSize($this->key);  
  129.     }  
  130.   
  131.     /** 
  132.      * 获取某一位置的值,不会删除该位置的值 
  133.      * @param $pos 
  134.      * @return mixed 
  135.      */  
  136.     public function view($pos)  
  137.     {  
  138.         return $this->redis_server->lGet($this->key, $pos);  
  139.     }  
  140.   
  141.     /** 
  142.      * 检查Redis扩展 
  143.      * @throws Exception 
  144.      */  
  145.     protected function check_environment()  
  146.     {  
  147.         if (!\extension_loaded('redis')) {  
  148.             throw new \Exception('Redis extension not loaded');  
  149.         }  
  150.     }  
  151. }  

如果需要一次写入多个队列,可以使用如下调用方式:

[php]  view plain  copy
  1. <?php  
  2. $redis = new RedisMessageQueue();  
  3. $redis->puts(1, 2, 3, 4);  
  4. $redis->puts(5, 6, 7, 8, 9);  

模仿HTTPSQS输出结果的封装如下,提供了写入位置和读取位置记录的功能:

[php]  view plain  copy
  1. <?php  
  2. /** 
  3.  * Created by PhpStorm. 
  4.  * User: huyanping 
  5.  * Date: 14-9-5 
  6.  * Time: 下午2:16 
  7.  * 
  8.  * 附加了队列状态信息的RedisMessageQueue 
  9.  */  
  10.   
  11. namespace Zebra\MessageQueue;  
  12.   
  13. class RedisMessageQueueStatus extends RedisMessageQueue {  
  14.   
  15.     protected $record_status;  
  16.   
  17.     protected $put_position;  
  18.   
  19.     protected $get_position;  
  20.   
  21.     public function __construct(  
  22.         $server_config = array('IP' => '127.0.0.1''PORT' => '6379'),  
  23.         $key = 'redis_message_queue',  
  24.         $p_connect = false,  
  25.         $record_status=true  
  26.     ){  
  27.         parent::__construct($server_config$key$p_connect);  
  28.         $this->record_status = $record_status;  
  29.         $this->put_position = $this->key . '_put_position';  
  30.         $this->get_position = $this->key . '_get_position';  
  31.     }  
  32.   
  33.     public function get(){  
  34.         if($queue = parent::get()){  
  35.             $incr_result = $this->redis_server->incr($this->get_position);  
  36.             if(!$incr_resultthrow new \Exception('can not mark get position,please check the redis server');  
  37.             return $queue;  
  38.         }else{  
  39.             return false;  
  40.         }  
  41.     }  
  42.   
  43.     public function put($message){  
  44.         if(parent::put($message)){  
  45.             $incr_result = $this->redis_server->incr($this->put_position);  
  46.             if(!$incr_resultthrow new \Exception('can not mark put position,please check the redis server');  
  47.             return true;  
  48.         }else{  
  49.             return false;  
  50.         }  
  51.     }  
  52.   
  53.     public function puts_status(){  
  54.         $message_array = func_get_args();  
  55.         $result = call_user_func_array(array($this'puts'), $message_array);  
  56.         if($result){  
  57.             $this->redis_server->incrBy($this->put_position, count($message_array));  
  58.             return true;  
  59.         }  
  60.         return false;  
  61.     }  
  62.   
  63.     public function size(){  
  64.         return $this->redis_server->lSize($this->key);  
  65.     }  
  66.   
  67.     public function status(){  
  68.         $status['put_position'] = ($put_position = $this->redis_server->get($this->put_position)) ? $put_position : 0;  
  69.         $status['get_position'] = ($get_position = $this->redis_server->get($this->get_position)) ? $get_position : 0;  
  70.         $status['unread_queue'] = $this->size();  
  71.         $status['queue_name'] = $this->key;  
  72.         $status['server'] = $this->server;  
  73.         $status['port'] = $this->port;  
  74.   
  75.         return $status;  
  76.     }  
  77.   
  78.     public function status_normal(){  
  79.         $status = $this->status();  
  80.         $message  = 'Redis Message Queue' . PHP_EOL;  
  81.         $message .= '-------------------' . PHP_EOL;  
  82.         $message .= 'Message queue name:' . $status['queue_name'] . PHP_EOL;  
  83.         $message .= 'Put position of queue:' . $status['put_position'] . PHP_EOL;  
  84.         $message .= 'Get position of queue:' . $status['get_position'] . PHP_EOL;  
  85.         $message .= 'Number of unread queue:' . $status['unread_queue'] . PHP_EOL;  
  86.   
  87.         return $message;  
  88.     }  
  89.   
  90.     public function status_json(){  
  91.         return \json_encode($this->status());  
  92.     }  
  93. }  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值