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 相关文章推荐
表单项的name命名为submit、reset引起的问题
Dec 22 Javascript
一段实现页面上的图片延时加载的js代码
Feb 11 Javascript
js获取url中指定参数值的示例代码
Dec 14 Javascript
使用js判断控件是否获得焦点
Jan 03 Javascript
Node.js中使用计时器定时执行函数详解
Aug 15 Javascript
node.js中的path.normalize方法使用说明
Dec 08 Javascript
全面了解js中的script标签
Jul 04 Javascript
Vue中的v-cloak使用解读
Mar 27 Javascript
使用Node.js搭建静态资源服务详细教程
Aug 02 Javascript
使用live-server快速搭建本地服务器+自动刷新的方法
Mar 09 Javascript
深入理解JavaScript的值传递和引用传递
Oct 24 Javascript
Vue2.0使用嵌套路由实现页面内容切换/公用一级菜单控制页面内容切换(推荐)
May 08 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实现WEB动态网页静态
2006/10/09 PHP
Laravel 5框架学习之向视图传送数据
2015/04/08 PHP
PHP控制反转(IOC)和依赖注入(DI)
2017/03/13 PHP
PHP生成随机码的思路与方法实例探索
2019/04/11 PHP
javaScript面向对象继承方法经典实现
2013/08/20 Javascript
jquery实现鼠标悬浮停止轮播特效
2020/08/20 Javascript
JavaScript常用函数工具集:lao-utils
2016/03/01 Javascript
javascript闭包概念简单解析(推荐)
2016/06/03 Javascript
node-http-proxy修改响应结果实例代码
2016/06/06 Javascript
JS实现颜色梯度与渐变效果完整实例
2016/12/30 Javascript
详解vue2.0 transition 多个元素嵌套使用过渡
2017/06/19 Javascript
extjs简介_动力节点Java学院整理
2017/07/17 Javascript
Vue2仿淘宝实现省市区三级联动
2020/04/15 Javascript
vue登录注册及token验证实现代码
2017/12/14 Javascript
windows10下python3.5 pip3安装图文教程
2018/04/02 Python
python迭代dict的key和value的方法
2018/07/06 Python
详解Python最长公共子串和最长公共子序列的实现
2018/07/07 Python
Python3随机漫步生成数据并绘制
2018/08/27 Python
Python 使用 attrs 和 cattrs 实现面向对象编程的实践
2019/06/12 Python
django中嵌套的try-except实例
2020/05/21 Python
Python爬虫小例子——爬取51job发布的工作职位
2020/07/10 Python
法国在线宠物店:zooplus.fr
2018/02/23 全球购物
什么是继承
2013/12/07 面试题
财会自我鉴定范文
2013/12/27 职场文书
优秀团支部事迹材料
2014/02/08 职场文书
十佳中学生事迹材料
2014/06/02 职场文书
医药公司采购员岗位职责
2014/09/12 职场文书
2014年维修工作总结
2014/11/22 职场文书
就业推荐表院系意见
2015/06/05 职场文书
幼儿园小班教学反思
2016/03/03 职场文书
2019最新版股权转让及委托持股协议书范本
2019/08/07 职场文书
经典哲理警句:志不真则心不热,心不热则功不贤
2019/11/14 职场文书
Python数据分析之pandas读取数据
2021/06/02 Python
OpenCV-Python直方图均衡化实现图像去雾
2021/06/07 Python
详细聊一聊mysql的树形结构存储以及查询
2022/04/05 MySQL
Spring IOC容器Bean的作用域及生命周期实例
2022/05/30 Java/Android