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 相关文章推荐
IE6/7/8中Option元素未设value时Select将获取空字符串
Apr 07 Javascript
Node.js 的异步 IO 性能探讨
Oct 08 Javascript
javascript中checkbox使用方法实例演示
Nov 19 Javascript
jQuery form 表单验证插件(fieldValue)校验表单
Jan 24 Javascript
JavaScript事件学习小结(一)事件流
Jun 09 Javascript
详解vue渲染从后台获取的json数据
Jul 06 Javascript
详解Layer弹出层样式
Aug 21 Javascript
vue 中动态绑定class 和 style的方法代码详解
Jun 01 Javascript
解决Vue axios post请求,后台获取不到数据的问题方法
Aug 11 Javascript
vue+php实现的微博留言功能示例
Mar 16 Javascript
vue 实现小程序或商品秒杀倒计时
Apr 14 Javascript
解决vue-router的beforeRouteUpdate不能触发
Apr 14 Vue.js
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如何得到当前页和上一页的地址?
2006/11/27 PHP
一个简单的网页密码登陆php代码
2012/07/17 PHP
php使用ICQ网关发送手机短信
2013/10/30 PHP
php抽象方法和抽象类实例分析
2016/12/07 PHP
PHP使用zlib扩展实现GZIP压缩输出的方法详解
2018/04/09 PHP
用js实现的页面关键字密度查询代码
2007/12/27 Javascript
你需要知道的10个最佳javascript开发实践小结
2012/04/15 Javascript
JQuery中阻止事件冒泡几种方式及其区别介绍
2014/01/15 Javascript
js 获取浏览器版本以此来调整CSS的样式
2014/06/03 Javascript
浅析js预加载/延迟加载
2014/09/25 Javascript
javascript中的遍历for in 以及with的用法
2014/12/22 Javascript
老生常谈JavaScript中的this关键字
2016/10/01 Javascript
jQuery操作复选框(CheckBox)的取值赋值实现代码
2017/01/10 Javascript
简单谈谈Javascript函数中的arguments
2017/02/09 Javascript
jQuery实现的上传图片本地预览效果简单示例
2018/03/29 jQuery
jQuery中元素选择器(element)简单用法示例
2018/05/14 jQuery
微信小程序如何调用json数据接口并解析
2019/06/29 Javascript
微信小程序 checkbox使用实例解析
2019/09/09 Javascript
Vue 中使用 typescript的方法详解
2020/02/17 Javascript
ES6字符串的扩展实例
2020/12/21 Javascript
利用 JavaScript 实现并发控制的示例代码
2020/12/31 Javascript
Python ORM框架SQLAlchemy学习笔记之安装和简单查询实例
2014/06/10 Python
python下载文件记录黑名单的实现代码
2017/10/24 Python
Python将图片转换为字符画的方法
2020/06/16 Python
Pandas之排序函数sort_values()的实现
2019/07/09 Python
用OpenCV将视频分解成单帧图片,图片合成视频示例
2019/12/10 Python
python 递归调用返回None的问题及解决方法
2020/03/16 Python
Python爬虫逆向分析某云音乐加密参数的实例分析
2020/12/04 Python
结婚喜宴主持词
2014/03/14 职场文书
爱国主义教育活动总结
2014/05/07 职场文书
2014年冬季防火方案
2014/05/21 职场文书
考试作弊检讨书
2015/01/27 职场文书
通知函的格式
2015/04/27 职场文书
毕业班工作总结
2015/08/10 职场文书
Java 数组的使用
2022/05/11 Java/Android
MySQL中order by的执行过程
2022/06/05 MySQL