PHP实现基于Redis的MessageQueue队列封装操作示例


Posted in Javascript onFebruary 02, 2019

本文实例讲述了PHP实现基于Redis的MessageQueue队列封装操作。分享给大家供大家参考,具体如下:

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

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

左进右出

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

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

基于Redis的PHP消息队列封装

<?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');
    }
  }
}

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

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

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

<?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());
  }
}

希望本文所述对大家PHP程序设计有所帮助。

Javascript 相关文章推荐
jQuery Ajax使用 全解析
Dec 15 Javascript
javascript通过className来获取元素的简单示例代码
Jan 10 Javascript
jQuery移除元素自动解绑事件实现思路及代码
May 31 Javascript
JavaScript bold方法入门实例(把指定文字显示为粗体)
Oct 17 Javascript
JavaScript检测上传文件大小的方法
Jul 22 Javascript
jQuery解决$符号命名冲突
Jun 18 Javascript
获取input标签的所有属性的方法
Jun 28 Javascript
小程序获取当前位置加搜索附近热门小区及商区的方法
Apr 08 Javascript
微信小程序网络层封装的实现(promise, 登录锁)
May 08 Javascript
使用xampp将angular项目运行在web服务器的教程
Sep 16 Javascript
Vue前端判断数据对象是否为空的实例
Sep 02 Javascript
vue中封装axios并实现api接口的统一管理
Dec 25 Vue.js
AngularJS实现的自定义过滤器简单示例
Feb 02 #Javascript
vue实现的树形结构加多选框示例
Feb 02 #Javascript
javascript中floor使用方法总结
Feb 02 #Javascript
JS对象和字符串之间互换操作实例分析
Feb 02 #Javascript
Vue+Element UI+Lumen实现通用表格分页功能
Feb 02 #Javascript
JS基于ES6新特性async await进行异步处理操作示例
Feb 02 #Javascript
JS使用canvas中的measureText方法测量字体宽度示例
Feb 02 #Javascript
You might like
php IP转换整形(ip2long)的详解
2013/06/06 PHP
解析PHP中如何将数组变量写入文件
2013/06/06 PHP
基于PHP导出Excel的小经验 完美解决乱码问题
2013/06/10 PHP
php输出echo、print、print_r、printf、sprintf、var_dump的区别比较
2013/06/21 PHP
php提高网站效率的技巧
2015/09/29 PHP
php图像处理函数imagecopyresampled用法详解
2016/12/02 PHP
js不能跳转到上一页面的问题解决方法
2013/03/01 Javascript
jquery限定文本框只能输入数字即整数和小数
2013/11/29 Javascript
jquery实现文本框数量加减功能的例子分享
2014/05/10 Javascript
JavaScript显示表单内元素数量的方法
2015/04/02 Javascript
js点击返回跳转到指定页面实现过程
2020/08/20 Javascript
AngularJS入门教程之过滤器用法示例
2016/11/02 Javascript
javascript 定时器工作原理分析
2016/12/03 Javascript
nodejs搭建本地http服务器教程
2017/03/13 NodeJs
JS获取子节点、父节点和兄弟节点的方法实例总结
2018/07/06 Javascript
ES6 Object.assign()的用法及其使用
2020/01/18 Javascript
js实现复制粘贴的两种方法
2020/12/04 Javascript
[01:03:38]2014 DOTA2国际邀请赛中国区预选赛5.21 CNB VS CIS
2014/05/22 DOTA
python正则表达式判断字符串是否是全部小写示例
2013/12/25 Python
python中执行shell的两种方法总结
2017/01/10 Python
Python 实现使用dict 创建二维数据、DataFrame
2018/04/13 Python
python 识别图片中的文字信息方法
2018/05/10 Python
使用PyInstaller将python转成可执行文件exe笔记
2018/05/26 Python
python tkinter之 复选、文本、下拉的实现
2020/03/04 Python
Python基于smtplib协议实现发送邮件
2020/06/03 Python
Python 使用生成器代替线程的方法
2020/08/04 Python
欧铁通票官方在线销售网站:Eurail.com
2017/10/14 全球购物
美国高品质个性化珠宝销售网站:Jewlr
2018/05/03 全球购物
波兰最早的运动鞋精品店之一:Street Supply
2019/08/29 全球购物
幼教毕业生自我鉴定
2014/01/12 职场文书
教师绩效考核方案
2014/01/21 职场文书
如何写好建议书
2014/03/13 职场文书
就业协议书
2014/09/12 职场文书
会计师事务所实习证明
2014/11/16 职场文书
入党申请书怎么写?
2019/06/21 职场文书
Python实现排序方法常见的四种
2021/07/15 Python