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 相关文章推荐
让div层随鼠标移动的实现代码 ie ff
Dec 18 Javascript
jQuery 技巧小结
Apr 02 Javascript
文本框输入时 实现自动提示(像百度、google一样)
Apr 05 Javascript
JavaScript自定义日期格式化函数详细解析
Jan 14 Javascript
js中settimeout方法加参数
Feb 28 Javascript
Window.Open如何在同一个标签页打开
Jun 20 Javascript
js返回前一页刷新本页重载页面
Jul 29 Javascript
jQuery实现可编辑的表格实例讲解(2)
Sep 17 Javascript
AngularJS实现自定义指令与控制器数据交互的方法示例
Jun 19 Javascript
Chart.js 轻量级HTML5图表绘制工具库(知识整理)
May 22 Javascript
jQuery实现的点击按钮改变样式功能示例
Jul 21 jQuery
NestJs使用Mongoose对MongoDB操作的方法
Feb 22 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
URL Rewrite的设置方法
2007/01/02 PHP
PHP中魔术变量__METHOD__与__FUNCTION__的区别
2014/09/29 PHP
php内嵌函数用法实例
2015/03/20 PHP
PHP扩展迁移为PHP7扩展兼容性问题记录
2016/02/15 PHP
PHP常用的三种设计模式汇总
2016/08/28 PHP
PHP copy函数使用案例代码解析
2020/09/01 PHP
PHP常量DIRECTORY_SEPARATOR原理及用法解析
2020/11/10 PHP
Jquery公告滚动+AJAX后台得到数据
2011/04/14 Javascript
顶部缓冲下拉菜单导航特效的JS代码
2013/08/27 Javascript
sencha touch 模仿tabpanel导航栏TabBar的实例代码
2013/10/24 Javascript
JS事件在IE与FF中的区别详细解析
2013/11/20 Javascript
js原型继承的两种方法对比介绍
2014/03/30 Javascript
JavaScript 消息框效果【实现代码】
2016/04/27 Javascript
Angularjs的ng-repeat中去除重复数据的方法
2016/08/05 Javascript
常用js,css文件统一加载方法(推荐) 并在加载之后调用回调函数
2016/09/23 Javascript
js字符串与Unicode编码互相转换
2017/05/17 Javascript
jQuery+CSS实现的标签页效果示例【测试可用】
2018/08/14 jQuery
Nodejs中的JWT和Session的使用
2018/08/21 NodeJs
vue中eslintrc.js配置最详细介绍
2018/12/21 Javascript
vue 自定义右键样式的实例代码
2019/11/06 Javascript
详解如何在Javascript和Sass之间共享变量
2019/11/13 Javascript
使用Vue生成动态表单
2019/11/26 Javascript
[05:31]干嘛呢兄弟!DOTA2 TI9语音轮盘部分出处
2019/05/14 DOTA
python脚本设置系统时间的两种方法
2016/02/21 Python
Python爬虫框架Scrapy实例代码
2018/03/04 Python
深入解析python中的实例方法、类方法和静态方法
2019/03/11 Python
Python遍历字典方式就实例详解
2019/12/28 Python
OpenCV哈里斯(Harris)角点检测的实现
2020/01/15 Python
基于python图像处理API的使用示例
2020/04/03 Python
美国祛痘、抗衰老药妆品牌:Murad
2016/08/27 全球购物
英国顶级水晶珠宝零售商之一:Tresor Paris
2019/04/27 全球购物
最新教师自我评价分享
2013/11/12 职场文书
简历中自我评价范文3则
2013/12/14 职场文书
个人整改措施书面材料
2014/10/24 职场文书
《植物妈妈有办法》教学反思
2016/02/23 职场文书
Windows server 2012 NTP时间同步的实现
2022/06/25 Servers