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 要点归纳(三) jQuery中的事件和动画(下:动画篇)
Mar 24 Javascript
JQuery入门——事件切换之toggle()方法应用介绍
Feb 05 Javascript
jQuery层次选择器选择元素使用介绍
Apr 18 Javascript
jQuery 借助插件Lavalamp实现导航条动态美化效果
Sep 27 Javascript
JavaScript中switch判断容易犯错的一个细节
Aug 27 Javascript
Javascript中arguments对象详解
Oct 22 Javascript
基于javascript制作微信聊天面板
Aug 09 Javascript
JavaScript模块化之使用requireJS按需加载
Apr 12 Javascript
Angular.js ng-file-upload结合springMVC的使用教程
Jul 10 Javascript
Vue自定义属性实例分析
Feb 23 Javascript
vue实现随机验证码功能的实例代码
Apr 30 Javascript
webpack DllPlugin xxx is not defined解决办法
Dec 13 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
smarty中post用法实例
2014/11/28 PHP
PHP实现的链式队列结构示例
2017/09/15 PHP
微信推送功能实现方式图文详解
2019/07/12 PHP
javascript 面向对象全新理练之继承与多态
2009/12/03 Javascript
EasyUI 中 MenuButton 的使用方法
2012/07/14 Javascript
jQuery选择器简明总结(含用法实例,一目了然)
2014/04/25 Javascript
js用拖动滑块来控制图片大小的方法
2015/02/27 Javascript
JavaScript小技巧整理
2015/12/30 Javascript
JavaScript+html5 canvas绘制渐变区域完整实例
2016/01/26 Javascript
浅谈jQuery 中的事件冒泡和阻止默认行为
2016/05/28 Javascript
前端JS面试中常见的算法问题总结
2016/12/23 Javascript
JavaScript利用Date实现简单的倒计时实例
2017/01/12 Javascript
Node.js Mongodb 密码特殊字符 @的解决方法
2017/04/11 Javascript
关于axios如何全局注册浅析
2018/01/14 Javascript
Vue二次封装axios为插件使用详解
2018/05/21 Javascript
基于vue实现移动端圆形旋钮插件效果
2018/11/28 Javascript
vue中axios的二次封装实例讲解
2019/10/14 Javascript
Python异常处理总结
2014/08/15 Python
python实现手机销售管理系统
2019/03/19 Python
Python中如何导入类示例详解
2019/04/17 Python
详解python websocket获取实时数据的几种常见链接方式
2019/07/01 Python
pycharm中显示CSS提示的知识点总结
2019/07/29 Python
CSS3圆角边框和边界图片效果实例
2016/07/01 HTML / CSS
用css3写出气球样式的示例代码
2017/09/11 HTML / CSS
丝芙兰巴西官方商城:SEPHORA巴西
2016/10/31 全球购物
企业管理部经理岗位职责
2013/12/24 职场文书
房地产开盘策划方案
2014/02/10 职场文书
写求职信要注意什么问题
2014/04/12 职场文书
远程网络教育毕业生自我鉴定
2014/04/14 职场文书
学期评语大全
2014/04/30 职场文书
2014新生大学四年计划书
2014/09/21 职场文书
2014年度安全工作总结
2014/12/04 职场文书
2014年酒店年度工作总结
2014/12/10 职场文书
2015年清明节活动总结
2015/02/09 职场文书
2016年党员公开承诺书范文
2016/03/24 职场文书
2019年幼儿园家长接送责任书
2019/10/29 职场文书