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 相关文章推荐
js 获取Listbox选择的值的代码
Apr 15 Javascript
document.getElementById的简写方式(获取id对象的简略写法)
Sep 10 Javascript
JS截取字符串常用方法整理及使用示例
Oct 18 Javascript
js离开或刷新页面检测(且兼容FF,IE,Chrome)
Mar 05 Javascript
项目中常用的JS方法整理
Jan 30 Javascript
手机软键盘弹出时影响布局的解决方法
Dec 15 Javascript
H5实现仿flash效果的实现代码
Sep 29 Javascript
Angular实现的敏感文字自动过滤与提示功能示例
Dec 29 Javascript
使用Angular CLI进行单元测试和E2E测试的方法
Mar 24 Javascript
详解写好JS条件语句的5条守则
Feb 28 Javascript
js中的深浅拷贝问题简析
May 10 Javascript
使用Taro实现小程序商城的购物车功能模块的实例代码
Jun 05 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中文件读、写、删的操作(PHP中对文件和目录操作)
2012/03/06 PHP
PHP 基于Yii框架中使用smarty模板的方法详解
2013/06/13 PHP
PHP中模拟处理HTTP PUT请求的例子
2014/07/22 PHP
PHP+MySQL统计该库中每个表的记录数并按递减顺序排列的方法
2016/02/15 PHP
非常实用的12个jquery代码片段
2015/11/02 Javascript
Jquery中map函数的用法
2016/06/03 Javascript
AngularJS入门教程之Helloworld示例
2016/12/25 Javascript
jQuery中弹出iframe内嵌页面元素到父页面并全屏化的实例代码
2016/12/27 Javascript
Javascript自定义事件详解
2017/01/13 Javascript
jQuery插件HighCharts绘制简单2D折线图效果示例【附demo源码】
2017/03/21 jQuery
jquery操作ul的一些操作笔记整理(干货)
2017/08/31 jQuery
nodejs分离html文件里面的js和css的方法
2019/04/09 NodeJs
深入学习Vue nextTick的用法及原理
2019/10/08 Javascript
vue 页面跳转的实现方式
2021/01/12 Vue.js
决策树的python实现方法
2014/11/18 Python
Python 加密的实例详解
2017/10/09 Python
python 处理dataframe中的时间字段方法
2018/04/10 Python
OpenCV3.0+Python3.6实现特定颜色的物体追踪
2019/07/23 Python
简单的Python调度器Schedule详解
2019/08/30 Python
Python基于requests实现模拟上传文件
2020/04/21 Python
CSS3使用多列制作瀑布流
2016/05/10 HTML / CSS
HTML高亮关键字的实现代码
2018/10/22 HTML / CSS
让IE9以下版本的浏览器兼容HTML5的方法
2014/03/12 HTML / CSS
德国电子商城:ComputerUniverse
2017/04/21 全球购物
英国灯具和灯泡网上商店:Lights.co.uk
2018/02/02 全球购物
亚马逊意大利站点:Amazon.it
2020/12/31 全球购物
什么叫应用程序域?什么是托管代码?什么是强类型系统?什么是装箱和拆箱?什么是重载?CTS、CLS和CLR分别作何解释?
2012/05/23 面试题
七年级生物教学反思
2014/01/30 职场文书
安全大检查反思材料
2014/01/31 职场文书
西门豹教学反思
2014/02/04 职场文书
2014年学习厉行节约反对浪费思想汇报
2014/09/10 职场文书
2015年妇联工作总结范文
2015/04/22 职场文书
2015年卫生院健康教育工作总结
2015/07/24 职场文书
再次探讨go实现无限 buffer 的 channel方法
2021/06/13 Golang
MySQL命令无法输入中文问题的解决方式
2021/08/30 MySQL
win10怎么设置右下角图标不折叠?Win10设置右下角图标不折叠的方法
2022/07/15 数码科技