alsc/streambus 问题修复 & 功能扩展

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

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

alsc/streambus

Composer 安装命令:

composer require alsc/streambus

包简介

Redis Streams message bus

README 文档

README

This library enables you to use Redis Streams as a message bus or queue.

At the technical level, Redis Streams Bus is a collection of Redis streams, each designated for a specific subject or message type, along with abstractions for working with them.

Features

  • Handle multiple message types and subjects within a single abstraction
  • Independent consumption via consumer groups with any required number of consumers
  • Ordered consumption within each subject
  • Recover consumption after failures
  • Delivery attempt counter
  • Place unprocessed messages into a DLQ (Dead Letter Queue)
  • Delay processing (NACK) for an arbitrary period in case of failure
  • Set a maximum time for message processing
  • Queue mode operation with deletion of processed items
  • Limit the time and number of stored messages
  • Tools for monitoring consumption and bus state

Requirements

  • PHP >= 8.2
  • Redis or Valkey >= 7.2

Installation

composer require alsc/streambus

Usage

The library provides a factory for configuring and creating the necessary classes. The main components and settings are described below. You can find more usage examples in the examples folder and in the tests of the repository.

Settings

Class StreamBus\StreamBusSettings

This class defines the settings for the entire message bus and is used during initialization of StreamBusBuilder and StreamBus.

Key Description Default
minTTLSec Minimum message TTL in stream 86400
maxSize Maximum messages stored per subject 1000000
exactLimits Apply exact limits detail false
deleteOnAck Delete message from stream on ACK false
deletePolicy How entries are removed when trimmed or acked with deleteOnAck. KeepRef / DelRef / Acked (Redis 8.2+) DeleteMode::KeepRef
maxDelivery Maximum delivery attempts per message. 0 means no limit 0
ackExplicit Require explicit ACK from consumers true
ackWaitMs Maximum time to process a message before it is redelivered 30 * 60 * 1000
nackDelayMs Minimum delay before a NACKed message is redelivered 0
idmpMode Idempotent publishing mode. None / Auto / Explicit (Redis 8.6+) IdmpMode::None
idmpDurationSec How long idempotency keys are retained. 0 uses the server default 0
idmpMaxSize Maximum number of idempotency keys retained per stream. 0 uses the server default 0
maxExpiredSubjects Maximum subjects scanned for expired messages per call. 0 means no limit 0

Example

$settings = new StreamBusSettings(
    minTTLSec: 86_400,
    maxSize: 10_000_000,
    exactLimits: false,
    deleteOnAck: false,
    maxDelivery: 10,
    ackWaitMs: 30 * 60 * 1000,
    //...
);

$builder = StreamBusBuilder::create('bus_name')
    ->withSettings($settings)
    //...

Produce

Class StreamBus\Producer\StreamBusProducerInterface

You can add messages to the bus either one by one or in batches.

Example

$serializers = [
    'users.new' => new StreamBusJsonSerializer(),
    'products.new' => new StreamBusJsonSerializer(),
];

$builder = StreamBusBuilder::create('bus_name')
    ->withClient($redisClient)
    ->withSettings(new StreamBusSettings())
    ->withSerializers($serializers);

$producer = $builder->createProducer('producer');
$producer->add('users.new', ['id' => 1, 'name' => 'David']);
$producer->add('users.new', ['id' => 2, 'name' => 'Andrew']);
$producer->add('products.new', ['id' => 1, 'product' => 'guitar']);
$producer->addMany('products.new', [
    ['id' => 1, 'product' => 'guitar']
    ['id' => 2, 'product' => 'flute']
]);

Consume

Class: StreamBus\Consumer\StreamBusConsumerInterface

There are several types of consumers for message consumption:

  • StreamBusConsumer - no order guaranties, at least once delivery
  • StreamBusOrderedConsumer - ordered per subject, at least once delivery
  • StreamBusOrderedStrictConsumer - same as previous with additional consistency checks

You can specify the subjects you are interested in when creating the consumers. Consumers support blocking reads.

Example

$serializers = [
    'users.new' => new StreamBusJsonSerializer(),
    'products.new' => new StreamBusJsonSerializer(),
    'orders.new' => new StreamBusJsonSerializer(),
];

$builder = StreamBusBuilder::create('bus_name')
    ->withClient($redisClient)
    ->withSettings(new StreamBusSettings())
    ->withSerializers($serializers);

$consumer = $builder->createConsumer('all', 'consumer');
// or
$consumer = $builder->createOrderedConsumer('users', ['users.new']);
// or
$consumer = $builder->createOrderedStrictConsumer('users_and_orders', ['users.new', 'orders.new']);

// Read max 5 messages per subject, block read for 10 seconds if no messages available to read
while ($messages = $consumer->read(5, 10_000)) {
    foreach ($messages as $subject => $subjectMessages) {
        foreach ($subjectMessages as $messageId => $message) {
            printf('got message from subject: %s, with id: %s' . PHP_EOL, $subject, $messageId);
            print_r($message);
            // ack
            $consumer->ack($subject, $messageId);
            // or nack
            $consumer->nack($subject, $messageId);
            // or nack with 10 seconds redelivery delay
            $consumer->nack($subject, $messageId, 10_000);
        }
    }
}

Consume with processor

Class StreamBus\Processor\StreamBusProcessor

You can also process messages using the processor.

Example

class User
{
    public function __construct(public int $id, public string $name) {}

    public function toArray(): array
    {
        return ['id' => $this->id, 'name' => $this->name];
    }

    public static function fromArray(array $data): self
    {
        return new self($data['id'], $data['name']);
    }
}

$builder = StreamBusBuilder::create('bus_name')
    ->withClient($redisClient)
    ->withSettings(new StreamBusSettings())
    ->withSerializers([
        'users.new' => new StreamBusJsonSerializer(
            static fn(User $user) => $user->toArray(),
            static fn(array $data) => User::fromArray($data),
        ),
    ]);

class UsersHandler
{
    public function __invoke(string $type, string $id, User $user): true
    {
        printf('Welcome, %s!' . PHP_EOL, $user->name);
        return true;
    }
}

$processor = $builder->createProcessor(
    'processor',
    'consumer',
    ['users.new' => new UsersHandler()]
)->process();

Dead Letter Queue

The bus supports working with a DLQ, placing messages there after maxDelivery delivery attempts. An example of usage can be found in the examples folder.

Observe

Class: StreamBus\StreamBus\StreamBusInfoInterface

Using this interface, you can obtain:

  • A list of existing subjects
  • A list of consumer groups for a specific subject
  • The number of messages taken for processing
  • The consumer group lag
  • Raw information about the state of the underlying Redis streams (details)

Example

$info = $builder->createBusInfo();

foreach ($info->getSubjects() as $subject) {
    printf('Subject: %s' . PHP_EOL, $subject);
    printf('  Stream length: %d' . PHP_EOL, $info->getStreamLength($subject));
    foreach ($info->getGroups($subject) as $group) {
        printf('  Group: %s' . PHP_EOL, $group);
        printf('    Pending: %d' . PHP_EOL, $info->getGroupPending($group, $subject));
        printf('    Time lag: %d' . PHP_EOL, $info->getGroupPending($group, $subject));
    }
}

Benchmark

The project includes benchmarks that you can run. It is recommended to adjust the test file configurations according to your hardware.

My 5-year-old home laptop is capable of processing around 100,000 messages per second in batch mode. On servers, I have achieved results of around 1 million messages per second in batch mode.

composer test:benchmark

Contributing

This project is open source and welcomes contributions from the community. If you have ideas, improvements, or bug fixes, feel free to open an issue or submit a pull request!

alsc/streambus 适用场景与选型建议

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

它主要适用于以下技术方向: 「redis」 「queue」 「stream」 「message」 「message bus」 「event bus」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

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

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

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

BUG 修复 & 性能优化

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

项目外包 & 长期维护

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

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

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-07-19