fair/queue 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

fair/queue

Composer 安装命令:

composer require fair/queue

包简介

README 文档

README

Shipped with PhpRedis BrokerInterface implementation.

Every message/job pushed into a queue has the fair-tag used to handle the message processing fairly, like so:

/**
 * @var BrokerInterface $broker
 */
$message = new SomeMessageOrJob(somePayload: 'user1-job1', fairTag: 'user1');
$broker->push($message);
$message = new SomeMessageOrJob(somePayload: 'user1-job2', fairTag: 'user1');
$broker->push($message);
$message = new SomeMessageOrJob(somePayload: 'user2-job1', fairTag: 'user2');
$broker->push($message);
$message = new SomeMessageOrJob(somePayload: 'user2-job2', fairTag: 'user2');
$broker->push($message);
$message = new SomeMessageOrJob(somePayload: 'user3-job1', fairTag: 'user3');
$broker->push($message);

while (($message = $broker->pop()) !== null) {
    echo $message->getSomePayload() . "\n";
}
//Output (not same order as in input):
//user1-job1
//user2-job1
//user3-job1
//user1-job2
//user2-job2

Requirements

Basic features

  • Fair messages distribution based on arbitrary string fair-tag
  • Messages with same fair-tag are handled in order of pushing
  • Pushing complexity: O(1)
  • Popping complexity: O(1) if there are no empty queues; O(m) where m is a number of empty (not all) queues (they are getting removed during pop operation)
  • Zero latency blocking popping support (forget about sleep(1);)
  • Endless flexibility: add as many workers as many connections your Redis instance can handle

Blocking VS Non-blocking pop

Non-blocking pop

  • returns NULL immediately if a queue is empty.
// NOT SAFE in case of an empty queue! It would cause 100% CPU load + constant Redis instance requests
while (true) {
    $message = $broker->pop();
    echo $message->getSomePayload() . "\n";
    //sleep(1); <= a classic solution to solve the 100% CPU problem
}

Blocking pop

  • returns a message immediately, if any.
  • else: waits for a new message for up to float timeout
  • returns NULL if there are no new messages when time is up, or returns a new message immediately (without waiting for the timeout to time up) if a new message appears.
// SAFE in case of an empty queue! Zero resources (both CPU + network traffic to Redis) usage during waiting
$timeout = 1.23; //seconds
while (true) {
    $message = $broker->popBlocking($timeout);
    echo $message->getSomePayload() . "\n";
}

Full working example

<?php

declare(strict_types=1);

require_once './vendor/autoload.php';

use Fair\Queue\Broker\Broker;
use Fair\Queue\Message\MessageInterface;
use Fair\Queue\Namer\PrefixQueueNamer;
use Fair\Queue\Serializer\PhpMessageSerializer;
use Fair\Queue\Storage\RedisStorage;
use Redis;

class SomeMessageOrJob implements MessageInterface
{
    private string $somePayload;
    private string|null $fairTag;

    public function __construct(
        string $somePayload,
        string|null $fairTag = null,
    ) {
        $this->fairTag = $fairTag;
        $this->somePayload = $somePayload;
    }

    public function getFairTag(): string|null
    {
        return $this->fairTag;
    }

    public function getSomePayload(): string
    {
        return $this->somePayload;
    }
}

$redis = new Redis([
    'host' => 'redis',
    'port' => 6379,
]);
$serilizer = new PhpMessageSerializer();
$namer = new PrefixQueueNamer(prefix: 'fair/queue');
$storage = new RedisStorage($redis, $serilizer);
$broker = new Broker($storage, $namer);
$message = new SomeMessageOrJob(somePayload: 'user1-job1', fairTag: 'user1');
$broker->push($message);
$message = new SomeMessageOrJob(somePayload: 'user1-job2', fairTag: 'user1');
$broker->push($message);
$message = new SomeMessageOrJob(somePayload: 'user2-job1', fairTag: 'user2');
$broker->push($message);
$message = new SomeMessageOrJob(somePayload: 'user2-job2', fairTag: 'user2');
$broker->push($message);
$message = new SomeMessageOrJob(somePayload: 'user3-job1', fairTag: 'user3');
$broker->push($message);

while (($message = $broker->pop()) !== null) {
    echo $message->getSomePayload() . "\n";
}
// Output:
// user1-job1
// user2-job1
// user3-job1
// user1-job2
// user2-job2

Testing

There is docker-compose.yaml for testing/development/experiments.

export REDIS_HOST=redis
export REDIS_PORT=6379
make test

fair/queue 适用场景与选型建议

fair/queue 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 0 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 02 月 10 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 fair/queue 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 fair/queue 我们能提供哪些服务?
定制开发 / 二次开发

基于 fair/queue 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 5
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: Unknown
  • 更新时间: 2025-02-10