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操作userdata
Apr 27 Javascript
javascript类继承机制的原理分析
Sep 12 Javascript
javascript返回顶部的按钮实现方法
Jan 09 Javascript
jQuery处理XML文件的几种方法
Jun 14 Javascript
jQuery实现右键菜单、遮罩等效果代码
Sep 27 Javascript
jQuery窗口拖动功能的实现代码
Feb 04 Javascript
解决layui 复选框等内置控件不显示的问题
Aug 14 Javascript
vue2实现搜索结果中的搜索关键字高亮的代码
Aug 29 Javascript
AngularJS修改model值时,显示内容不变的实例
Sep 13 Javascript
浅谈对于react-thunk中间件的简单理解
May 01 Javascript
vue cli 3.0通用打包配置代码,不分一二级目录
Sep 02 Javascript
JavaScript实现移动小精灵的案例代码
Dec 12 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短域名转换为实际域名函数
2011/01/17 PHP
Thinkphp使用mongodb数据库实现多条件查询方法
2014/06/26 PHP
php中Array2xml类实现数组转化成XML实例
2014/12/08 PHP
2款PHP无限级分类实例代码
2015/11/11 PHP
ThinkPHP实现分页功能
2017/04/28 PHP
php表单处理操作
2017/11/16 PHP
Nodejs学习笔记之Stream模块
2015/01/13 NodeJs
jquery分析文本里url或邮件地址为真实链接的方法
2015/06/20 Javascript
jQuery图片缩放插件smartZoom使用实例详解
2017/08/25 jQuery
基于Vue实现关键词实时搜索高亮显示关键词
2018/07/21 Javascript
Vue.js 中的 v-model 指令及绑定表单元素的方法
2018/12/03 Javascript
微信小程序实现日历效果
2018/12/28 Javascript
JavaScript相等运算符的九条规则示例详解
2019/10/20 Javascript
微信小程序 获取手机号 JavaScript解密示例代码详解
2020/05/14 Javascript
[01:59]游戏“zheng”当时试玩会
2019/08/21 DOTA
[42:24]完美世界DOTA2联赛循环赛 LBZS vs DM BO2第一场 11.01
2020/11/02 DOTA
python中的sort方法使用详解
2014/07/25 Python
Python import自定义模块方法
2015/02/12 Python
简单讲解Python中的数字类型及基本的数学计算
2016/03/11 Python
详解 Python 与文件对象共事的实例
2017/09/11 Python
对python中两种列表元素去重函数性能的比较方法
2018/06/29 Python
Python实现矩阵相乘的三种方法小结
2018/07/26 Python
使用Python编写Prometheus监控的方法
2018/10/15 Python
python如何将两个txt文件内容合并
2019/10/18 Python
Python for循环与getitem的关系详解
2020/01/02 Python
使用python处理题库表格并转化为word形式的实现
2020/04/14 Python
Python命名空间namespace及作用域原理解析
2020/06/05 Python
解析Tensorflow之MNIST的使用
2020/06/30 Python
Django windows使用Apache实现部署流程解析
2020/10/12 Python
详解selenium + chromedriver 被反爬的解决方法
2020/10/28 Python
HTML5事件方法全部汇总
2016/05/12 HTML / CSS
宿舍违规用电检讨书
2014/02/16 职场文书
活动总结模板
2014/05/09 职场文书
邀请函怎么写
2015/01/30 职场文书
医学会议开幕词
2016/03/03 职场文书
Python批量将csv文件转化成xml文件的实例
2021/05/10 Python