- Introduction
- Features
- Installation
- Quick Start
- Usage
- Configuration
- Advanced Usage
- Best Practices
- Potential Pitfalls
- Contributing
- License
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.
- 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
- PHP >= 8.1
- Symfony >= 7.3
- Redis (recommended for distributed sequence safety)
composer require tourze/symfony-snowflake-bundleAdd to config/bundles.php:
return [
// ...
Tourze\SnowflakeBundle\SnowflakeBundle::class => ['all' => true],
];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;
}
}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();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
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-31This ensures different server instances generally get different WorkerIds without manual configuration.
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.
For basic usage, no extra configuration is required. The bundle works with sensible defaults.
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.
- 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
BIGINTin databases (or strings if your DB doesn't support 64-bit integers) - Benchmarking: Test performance in your environment as high throughput may require tuning
- 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
- 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
Issues and pull requests are welcome! Please visit the GitHub repository to contribute.
This bundle is available under the MIT License. See the LICENSE file for more information.