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 相关文章推荐
utf-8编码引起js输出中文乱码的解决办法
Jun 23 Javascript
ExtJs 表单提交登陆实现代码
Aug 19 Javascript
EXTJS FORM HIDDEN TEXTFIELD 赋值 使用value不好用的问题
Apr 16 Javascript
JavaScript中最简洁的编码html字符串的方法
Oct 11 Javascript
JS仿百度自动下拉框模糊匹配提示
Jul 25 Javascript
jquery结合html实现中英文页面切换
Nov 29 Javascript
微信小程序 PHP生成带参数二维码
Feb 21 Javascript
微信小程序三级联动地址选择器的实例代码
Jul 12 Javascript
jQuery plugin animsition使用小结
Sep 14 jQuery
Angular2+如何去除url中的#号详解
Dec 20 Javascript
部署vue+Springboot前后端分离项目的步骤实现
May 31 Javascript
详解element-ui动态限定的日期范围选择器代码片段
Jul 03 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
《Pokemon Sword·Shield》系列WEB动画《薄明之翼》第2话声优阵容公开!
2020/03/06 日漫
重置版战役片段
2020/04/09 魔兽争霸
透析PHP的配置文件php.ini
2006/10/09 PHP
处理单名多值表单的详解
2013/06/08 PHP
composer.lock文件的作用
2016/02/03 PHP
Thinkphp 3.2框架使用Redis的方法详解
2019/10/24 PHP
php 自定义函数实现将数据 以excel 表格形式导出示例
2019/11/13 PHP
JavaScript调用Activex控件的事件的实现方法
2010/04/11 Javascript
JavaScript操作XML实例代码(获取新闻标题并分页,并分页)
2010/05/25 Javascript
通过JS自动隐藏手机浏览器的地址栏实现原理与代码
2013/01/02 Javascript
Jquery 实现表格颜色交替变化鼠标移过颜色变化实例
2013/08/28 Javascript
Nodejs学习笔记之入门篇
2015/04/16 NodeJs
Bootstrap弹出带合法性检查的登录框实例代码【推荐】
2016/06/23 Javascript
Jquery表单验证失败后不提交的解决方法
2016/10/18 Javascript
详解JavaScript常量定义
2017/01/03 Javascript
微信小程序 form组件详解及简单实例
2017/01/10 Javascript
Vue中对比scoped css和css module的区别
2018/05/17 Javascript
vue过滤器实现日期格式化的案例分析
2020/07/02 Javascript
解决vue scoped scss 无效的问题
2020/09/04 Javascript
python字符串中的单双引
2017/02/16 Python
tensorflow 输出权重到csv或txt的实例
2018/06/14 Python
Windows 64位下python3安装nltk模块
2018/09/19 Python
Python中字符串List按照长度排序
2019/07/01 Python
python代码实现逻辑回归logistic原理
2019/08/07 Python
利用python计算时间差(返回天数)
2019/09/07 Python
pygame实现俄罗斯方块游戏(基础篇2)
2019/10/29 Python
python 普通克里金(Kriging)法的实现
2019/12/19 Python
Python实现实时数据采集新型冠状病毒数据实例
2020/02/04 Python
Python发送手机动态验证码代码实例
2020/02/28 Python
VScode连接远程服务器上的jupyter notebook的实现
2020/04/23 Python
tensorflow实现残差网络方式(mnist数据集)
2020/05/26 Python
python des,aes,rsa加解密的实现
2021/01/16 Python
《最可爱的人》教学反思
2014/02/14 职场文书
《棉鞋里的阳光》教学反思
2014/04/24 职场文书
MySQL常见优化方案汇总
2022/01/18 MySQL
一文弄懂MySQL中redo log与binlog的区别
2022/02/15 MySQL