tourze/symfony-snowflake-bundle

Symfony Bundle for Snowflake ID generation with Redis support

Installs: 20 560

Dependents: 8

Suggesters: 0

Security: 0

Stars: 2

Watchers: 1

Forks: 0

Open Issues: 0

Type:symfony-bundle

pkg:composer/tourze/symfony-snowflake-bundle

This package is auto-updated.

Last update: 2025-10-31 17:21:02 UTC


README

English | 中文

Packagist

PHP Version

Build Status

Coverage Status

License

Table of Contents

Introduction

A high-performance, distributed Snowflake ID generator bundle for Symfony applications. This bundle implements Twitter's Snowflake algorithm to generate unique, time-ordered, 64-bit IDs for distributed systems. It is designed for scenarios requiring globally unique IDs under high concurrency.

Features

  • Generates 64-bit unique IDs based on godruoyi/php-snowflake library
  • Built-in Redis sequence resolver to ensure uniqueness in high-concurrency environments
  • Auto-generates WorkerId based on hostname for distributed scenario support
  • Zero configuration required for basic usage
  • Fully compatible with Symfony 7.3+
  • Graceful fallback from Redis to RandomSequenceResolver when Redis is unavailable
  • Autowiring support for easy integration with Symfony services
  • Thread-safe ID generation
  • Time-ordered IDs for efficient database indexing

Installation

Requirements

  • PHP >= 8.1
  • Symfony >= 7.3
  • Redis (recommended for distributed sequence safety)

Install via Composer

composer require tourze/symfony-snowflake-bundle

Quick Start

1. Register the Bundle (if not auto-discovered)

Add to config/bundles.php:

return [
    // ...
    Tourze\SnowflakeBundle\SnowflakeBundle::class => ['all' => true],
];

2. Generate a Snowflake ID

Inject the Snowflake service into your service or controller:

<?php

namespace App\Service;

use Tourze\SnowflakeBundle\Service\Snowflake;

class ProductService
{
    public function __construct(
        private readonly Snowflake $snowflake
    ) {
    }

    public function createProduct(): int|string
    {
        // Generate a unique ID for your new product
        $uniqueId = $this->snowflake->id();
        
        // Use the ID in your application logic
        return $uniqueId;
    }
}

Usage

Basic Usage

Simply inject the Snowflake service and call the id() method:

// Inject via constructor
public function __construct(private readonly Snowflake $snowflake) {}

// Generate a unique ID
$id = $this->snowflake->id();

ID Format and Structure

The generated ID is a 64-bit integer with the following structure:

  • 41 bits for timestamp (milliseconds since the epoch or custom epoch)
  • 10 bits for worker ID (machine ID)
  • 12 bits for sequence number (per millisecond counter)

This structure allows for:

  • ~69 years of unique timestamps from custom epoch
  • 1024 different worker IDs
  • 4096 IDs per millisecond per worker

WorkerId Generation

By default, the WorkerId is automatically derived from the hostname using a CRC32 hash modulo operation:

$workerId = crc32(gethostname()) % 32; // Returns a value between 0-31

This ensures different server instances generally get different WorkerIds without manual configuration.

Redis-Based Sequence Resolver

When Redis is available, the bundle automatically uses RedisSequenceResolver for:

  • Enhanced uniqueness guarantees under high concurrency
  • Improved resistance to clock drift
  • Better distribution of IDs across multiple instances

When Redis is unavailable, it gracefully falls back to RandomSequenceResolver to ensure service availability.

Configuration

For basic usage, no extra configuration is required. The bundle works with sensible defaults.

Advanced Usage

Custom Sequence Resolver

For more advanced scenarios, you may extend the ResolverFactory to provide a custom sequence resolver:

<?php

namespace App\Service;

use Godruoyi\Snowflake\SequenceResolver;
use Tourze\SnowflakeBundle\Service\ResolverFactory;

class CustomResolverFactory extends ResolverFactory
{
    public function resolver(): SequenceResolver
    {
        // Your custom resolver implementation
        return new YourCustomSequenceResolver();
    }
}

Then register your custom factory in your service configuration.

Best Practices

  • Redis in Production: Always use Redis in production environments for sequence distribution
  • Clock Synchronization: Ensure your server clocks are synchronized with NTP
  • Worker ID Management: For large distributed deployments, consider implementing a centralized WorkerId assignment mechanism
  • ID Storage: Store Snowflake IDs as BIGINT in databases (or strings if your DB doesn't support 64-bit integers)
  • Benchmarking: Test performance in your environment as high throughput may require tuning

Potential Pitfalls

  • Clock Moving Backwards: If server time moves backward due to NTP adjustments, duplicate IDs might be generated
  • Worker ID Conflicts: In very large deployments, hostname-based WorkerId generation might lead to conflicts
  • Performance without Redis: Without Redis, high concurrency might lead to duplicates under extreme circumstances

Changelog

0.0.x

  • Initial release with Snowflake ID generation support
  • Redis-based sequence resolver with graceful fallback
  • Automatic WorkerId generation based on hostname
  • Full Symfony 7.3+ integration with autowiring support

Contributing

Issues and pull requests are welcome! Please visit the GitHub repository to contribute.

License

This bundle is available under the MIT License. See the LICENSE file for more information.