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 相关文章推荐
获取HTML DOM节点元素的方法的总结
Aug 21 Javascript
jQuery获取iframe的document对象的方法
Oct 10 Javascript
jQuery搜索同辈元素方法
Feb 10 Javascript
JavaScript实现向OL列表内动态添加LI元素的方法
Mar 21 Javascript
JS判断图片是否加载完成方法汇总(最新版)
May 13 Javascript
AngularJs Javascript MVC 框架
Jun 20 Javascript
JavaScript中const、var和let区别浅析
Oct 11 Javascript
详解ES6中的let命令
Apr 05 Javascript
微信小程序实现实时圆形进度条的方法示例
Feb 24 Javascript
用node开发并发布一个cli工具的方法步骤
Jan 03 Javascript
详解VUE Element-UI多级菜单动态渲染的组件
Apr 25 Javascript
微信小程序实现列表左右滑动
Nov 19 Javascript
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动态图像的创建
2006/10/09 PHP
Smarty变量用法详解
2016/05/11 PHP
php错误日志简单配置方法
2016/07/11 PHP
PHP加密解密类实例代码
2016/07/20 PHP
php命令行模式代码实例详解
2021/02/26 PHP
TP - 比RBAC更好的权限认证方式(Auth类认证)
2021/03/09 PHP
js获取当前select 元素值的代码
2010/04/19 Javascript
js获取UserControl内容为拼html时提供方便
2014/11/02 Javascript
简介AngularJS的视图功能应用
2015/06/17 Javascript
JavaScript模板引擎Template.js使用详解
2016/12/15 Javascript
微信小程序 picker 组件详解及简单实例
2017/01/10 Javascript
JavaScript自定义分页样式
2017/01/17 Javascript
jquery实现刷新随机变化样式特效(tag标签样式)
2017/02/03 Javascript
微信小程序多张图片上传功能
2017/06/07 Javascript
使用electron实现百度网盘悬浮窗口功能的示例代码
2018/10/24 Javascript
原生js实现弹幕效果
2020/11/29 Javascript
[02:45]DOTA2英雄敌法师基础教程
2013/11/25 DOTA
[05:46]2018完美盛典-《同梦共竞》
2018/12/17 DOTA
Python实现把utf-8格式的文件转换成gbk格式的文件
2015/01/22 Python
python构建自定义回调函数详解
2017/06/20 Python
python 通过麦克风录音 生成wav文件的方法
2019/01/09 Python
Appium+python自动化怎么查看程序所占端口号和IP
2019/06/14 Python
Python及Pycharm安装方法图文教程
2019/08/05 Python
详解Python 中sys.stdin.readline()的用法
2019/09/12 Python
python实现tail实时查看服务器日志示例
2019/12/24 Python
PyCharm永久激活方式(推荐)
2020/09/22 Python
Python脚本导出为exe程序的方法
2020/03/25 Python
python安装读取grib库总结(推荐)
2020/06/24 Python
Python模拟登录requests.Session应用详解
2020/11/17 Python
入股协议书
2014/04/14 职场文书
物业保安岗位职责
2014/07/02 职场文书
现实表现材料范文
2014/12/23 职场文书
总经理司机岗位职责
2015/04/10 职场文书
报案材料怎么写
2015/05/25 职场文书
2016年班主任新年寄语
2015/08/18 职场文书
nginx容器方式反向代理实战
2022/04/18 Servers