基于Redis的MessageQueue队列封装

来源:互联网 发布:淘宝图片怎么拍 编辑:程序博客网 时间:2024/06/06 12:56

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的消息队列封装
 */
namespaceZebra\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
     */
    publicfunction __construct($server_config= array('IP'=> '127.0.0.1','PORT' => '6379'),$key = 'redis_message_queue',$p_connect = false)
    {
        if(empty($key))
            thrownew \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链接,使用长连接时,最好主动调用关闭
     */
    publicfunction __destruct()
    {
        $this->close();
    }
 
    /**
     * 短连接
     */
    privatefunction connect()
    {
        $this->redis_server =new \Redis();
        $this->redis_server->connect($this->server,$this->port);
    }
 
    /**
     * 长连接
     */
    publicfunction pconnect()
    {
        $this->redis_server =new \Redis();
        $this->redis_server->pconnect($this->server,$this->port);
    }
 
    /**
     * 关闭链接
     */
    publicfunction close()
    {
        $this->redis_server->close();
    }
 
    /**
     * 向队列插入一条信息
     * @param $message
     * @return mixed
     */
    publicfunction put($message)
    {
        return$this->redis_server->lPush($this->key,$message);
    }
 
    /**
     * 向队列中插入一串信息
     * @param $message
     * @return mixed
     */
    publicfunction puts(){
        $params= func_get_args();
        $message_array= array_merge(array($this->key),$params);
        returncall_user_func_array(array($this->redis_server,'lPush'), $message_array);
    }
 
    /**
     * 从队列顶部获取一条记录
     * @return mixed
     */
    publicfunction get()
    {
        return$this->redis_server->lPop($this->key);
    }
 
    /**
     * 选择数据库,可以用于区分不同队列
     * @param $database
     */
    publicfunction select($database)
    {
        $this->redis_server->select($database);
    }
 
    /**
     * 获得队列状态,即目前队列中的消息数量
     * @return mixed
     */
    publicfunction size()
    {
        return$this->redis_server->lSize($this->key);
    }
 
    /**
     * 获取某一位置的值,不会删除该位置的值
     * @param $pos
     * @return mixed
     */
    publicfunction view($pos)
    {
        return$this->redis_server->lGet($this->key,$pos);
    }
 
    /**
     * 检查Redis扩展
     * @throws Exception
     */
    protectedfunction check_environment()
    {
        if(!\extension_loaded('redis')) {
            thrownew \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
 */
 
namespaceZebra\MessageQueue;
 
class RedisMessageQueueStatus extends RedisMessageQueue {
 
    protected$record_status;
 
    protected$put_position;
 
    protected$get_position;
 
    publicfunction __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';
    }
 
    publicfunction 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{
            returnfalse;
        }
    }
 
    publicfunction 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');
            returntrue;
        }else{
            returnfalse;
        }
    }
 
    publicfunction 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));
            returntrue;
        }
        returnfalse;
    }
 
    publicfunction size(){
        return$this->redis_server->lSize($this->key);
    }
 
    publicfunction 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;
    }
 
    publicfunction 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;
    }
 
    publicfunction status_json(){
        return\json_encode($this->status());
    }
}
0 0
原创粉丝点击