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 相关文章推荐
html+css+js实现xp window界面及有关功能
Mar 26 Javascript
js判断浏览器版本以及浏览器内核的方法
Jan 20 Javascript
js简单实现点击左右运动的方法
Apr 10 Javascript
浅谈Javascript中的12种DOM节点类型
Aug 19 Javascript
AJAX和jQuery动态加载数据的实现方法
Dec 05 Javascript
AngularJS获取json数据的方法详解
May 27 Javascript
微信小程序与php 实现微信支付的简单实例
Jun 23 Javascript
vue路由嵌套的SPA实现步骤
Nov 06 Javascript
javaScript中&quot;==&quot;和&quot;===&quot;的区别详解
Mar 16 Javascript
关于TypeScript模块导入的那些事
Jun 12 Javascript
微信小程序制作表格的方法
Feb 14 Javascript
处理canvas绘制图片模糊问题
May 11 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 current函数获取未知字符键名数组第一个元素的值
2013/06/24 PHP
php class类的用法详细总结
2013/10/17 PHP
给artDialog 5.02 增加ajax get功能详细介绍
2012/11/13 Javascript
javascript 二进制运算技巧解析
2012/11/27 Javascript
javascript中的parseInt和parseFloat区别
2013/07/12 Javascript
Javascript学习指南
2014/12/01 Javascript
AngularJS中使用HTML5手机摄像头拍照
2016/02/22 Javascript
js实现ctrl+v粘贴上传图片(兼容chrome、firefox、ie11)
2016/03/09 Javascript
JS把内容动态插入到DIV的实现方法
2016/07/19 Javascript
微信小程序之仿微信漂流瓶实例
2016/12/09 Javascript
vue-resource调用promise取数据方式详解
2017/07/21 Javascript
详解vue mixins和extends的巧妙用法
2017/12/20 Javascript
React 组件渲染和更新的实现代码示例
2019/02/21 Javascript
layui自定义验证,用ajax查询后台是否有重复数据,form.verify的例子
2019/09/06 Javascript
[01:06:07]2014 DOTA2国际邀请赛中国区预选赛5.21 DT VS CIS
2014/05/22 DOTA
python执行子进程实现进程间通信的方法
2015/06/02 Python
python结合shell查询google关键词排名的实现代码
2016/02/27 Python
Python 多线程实例详解
2017/03/25 Python
Python 网页解析HTMLParse的实例详解
2017/08/10 Python
django ajax json的实例代码
2018/05/29 Python
django 实现电子支付功能的示例代码
2018/07/25 Python
在cmder下安装ipython以及环境的搭建
2018/10/19 Python
python random从集合中随机选择元素的方法
2019/01/23 Python
Python函数式编程实例详解
2020/01/17 Python
python with (as)语句实例详解
2020/02/04 Python
英国泽西岛植物:Jersey Plants Direct
2019/08/07 全球购物
adidas瑞典官方网站:购买阿迪达斯鞋子和运动服
2019/12/11 全球购物
探亲邀请信范文
2014/01/30 职场文书
军训自我鉴定100字
2014/02/13 职场文书
消防标语大全
2014/06/07 职场文书
党建目标管理责任书
2014/07/25 职场文书
工厂清洁工岗位职责
2015/02/14 职场文书
OpenCV-Python直方图均衡化实现图像去雾
2021/06/07 Python
Redis Cluster集群动态扩容的实现
2021/07/15 Redis
MySQL连接控制插件介绍
2021/09/25 MySQL
SpringBoot2零基础到精通之数据与页面响应
2022/03/22 Java/Android