グローバル一意IDの設計特性
-
グローバル一意性 分散システム全体で重複しない一意な識別子を生成する必要があります。
-
高可用性 水平スケーリングやクラスタ構成により、ノード障害時でも継続的なID生成を保証します。
-
セキュリティ 業務ロジックとは独立した専用コンポーネントとして設計し、複数サービス間での共有を可能にします。
-
高パフォーマンス 短時間で大量のIDを生成可能な処理を実現します。
-
順序性 生成時刻に基づくソート可能なID構造を提供します。
タイムスタンプ+カウンタ方式
// ビット構成
符号ビット: 1bit(常に0)
時間差分: 31bit(69年間使用可能)
カウンタ: 32bit(秒単位で42億9496万7296個生成可能)
Redisカウンタ実装例
// データ型変更(String→Long)
String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
Long counter = redisTemplate.opsForValue().increment("prefix:" + businessType + ":" + date);
処理フロー
-
日付フォーマット処理
LocalDateTimeオブジェクトをyyyy/MM/dd形式に変換し、日次単位の識別キーを生成します。 -
Redisカウンタ操作
- キー構成:
prefix:{ビジネス種別}:{日付} incrementコマンドでアトミックなカウンタ増分を実現- 未初期化キーの場合は0から開始
Java実装コード
/**
* Redisを基盤とした分散ID生成クラス
*/
@Component
public class UniqueIdGenerator {
// 基準時刻(2021/01/01 00:00:00 UTC)
private static final long BASE_EPOCH = 1609459200L;
// カウンタビット長
private static final int COUNTER_BITS = 32;
@Autowired
private RedisTemplate<String, String> redisTemplate;
/**
* 一意ID生成メソッド
* @param businessType ビジネスカテゴリ
* @return 64bit一意ID
*/
public synchronized long createUniqueID(String businessType) {
// 現在時刻取得と基準時刻からの差分計算
long currentEpoch = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
long timeDiff = currentEpoch - BASE_EPOCH;
// 日次カウンタキー生成
String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
String counterKey = String.format("counter:%s:%s", businessType, dateStr);
// Redisカウンタ操作
Long sequence = redisTemplate.opsForValue().increment(counterKey);
// ビット演算によるID合成
return (timeDiff << COUNTER_BITS) | sequence;
}
}