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 load方法用法集锦
Dec 06 Javascript
利用Jquery实现可多选的下拉框
Feb 21 Javascript
SuperSlide标签切换、焦点图多种组合插件
Mar 14 Javascript
Bootstrap笔记之缩略图、警告框实例详解
Mar 09 Javascript
jQuery阻止移动端遮罩层后页面滚动
Mar 15 Javascript
vue-router重定向不刷新问题的解决
Jun 25 Javascript
微信小程序表单验证form提交错误提示效果
Jun 19 Javascript
Vue开发之封装上传文件组件与用法示例
Apr 25 Javascript
Vue动态组件和异步组件原理详解
May 06 Javascript
微信小程序 扭蛋抽奖机css3动画实现详解
Jul 19 Javascript
vue2.x数组劫持原理的实现
Apr 19 Javascript
JavaScript小技巧带你提升你的代码技能
Sep 15 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(2)――PHP类型
2010/02/15 PHP
php做下载文件的实现代码及文件名中乱码解决方法
2011/02/03 PHP
php数组函数序列之array_key_exists() - 查找数组键名是否存在
2011/10/29 PHP
微信支付开发告警通知实例
2016/07/12 PHP
PHP分享图片的生成方法
2018/04/25 PHP
TP5框架实现自定义分页样式的方法示例
2020/04/05 PHP
PHP Web表单生成器案例分析
2020/06/02 PHP
分享几种好用的PHP自定义加密函数(可逆/不可逆)
2020/09/15 PHP
Jquery插件之多图片异步上传
2010/10/20 Javascript
Node.js:Windows7下搭建的Node.js服务(来玩玩服务器端的javascript吧,这可不是前端js插件)
2011/06/27 Javascript
JS iFrame加载慢怎么解决
2016/05/13 Javascript
EasyUI在表单提交之前进行验证的实例代码
2016/06/24 Javascript
详解angularJs中关于ng-class的三种使用方式说明
2017/06/02 Javascript
IE9 elementUI文件上传的问题解决
2018/10/17 Javascript
Vue render函数实战之实现tabs选项卡组件
2019/04/22 Javascript
vue transition 在子组件中失效的解决
2019/11/12 Javascript
vue+elementUI(el-upload)图片压缩,默认同比例压缩操作
2020/08/10 Javascript
[02:27]2018DOTA2亚洲邀请赛赛前采访-OpTic
2018/04/03 DOTA
Windows下PyMongo下载及安装教程
2015/04/27 Python
余弦相似性计算及python代码实现过程解析
2019/09/18 Python
基于Python实现扑克牌面试题
2019/12/11 Python
django迁移文件migrations的实现
2020/03/31 Python
Python3通过chmod修改目录或文件权限的方法示例
2020/06/08 Python
Python requests上传文件实现步骤
2020/09/15 Python
用纯CSS3实现网页中常见的小箭头
2017/10/16 HTML / CSS
探索HTML5本地存储功能运用技巧
2016/03/02 HTML / CSS
阿迪达斯德国官方网站:adidas德国
2017/07/12 全球购物
台湾百利市购物中心:e-Payless
2017/08/16 全球购物
自我鉴定写作要点
2014/01/17 职场文书
《阳光》教学反思
2014/02/23 职场文书
俄语专业职业生涯规划
2014/02/26 职场文书
中学生国旗下讲话稿
2014/04/26 职场文书
2014年国庆节广播稿
2014/09/19 职场文书
农村党支部书记四风问题个人对照检查材料
2014/09/21 职场文书
2014年护士个人工作总结
2014/11/11 职场文书
Python爬取奶茶店数据分析哪家最好喝以及性价比
2022/09/23 Python