基于Redis的MessageQueue队列封装

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

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

左进右出

1
2
$redis ->lPush( $key , $value );
$redis ->rPop( $key );

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

基于Redis的PHP消息队列封装

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

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

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值