Redis 實現全局唯一 ID

分佈式系統中由於跨進程跨系統,在某些場景中,我們需要生成全局的唯一 ID,例如訂單系統,併發情況下,不同的系統需要同時生成不一樣的訂單 ID 方便後續的訂單下單與查詢等等。

全局唯一 ID 生成策略

  1. UUID

  2. Redis 自增

  3. snowflake 算法

  4. 數據庫自增

  5. 百度開源的 UidGenerator

  6. 美圖點評的 Leaf

Redis 自增 ID 策略

ID 的組成部分:

利用 redis 生成全局唯一 ID,其實 redis 扮演的角色就是一個計數器的作用,方便後續的統計。

  • 優點:高性能,高併發,唯一性,遞增性,安全性。

  • 缺點:需要依賴 redis 去實現

代碼實現

/**
 * @author issavior
 */
@Component
public class RedisIdWorker {
    /**
     * 開始時間戳
     */
    private static final long BEGIN_TIMESTAMP = 1640995200L;
    /**
     * 序列號的位數
     */
    private static final int COUNT_BITS = 32;

    private final StringRedisTemplate stringRedisTemplate;

    public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    public long nextId(String keyPrefix) {
        // 1.生成時間戳
        LocalDateTime now = LocalDateTime.now();
        long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
        long timestamp = nowSecond - BEGIN_TIMESTAMP;

        // 2.生成序列號
        // 2.1.獲取當前日期,精確到天
        String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
        // 2.2.自增長
        Long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date);

        // 3.拼接並返回
        return timestamp << COUNT_BITS | (count == null ? 0 : count);
    }
    /**
     * 獲取2022年1月1號0點0時0分的時間戳
     * @param args
     */
    public static void main(String[] args) {
        LocalDateTime startLocalTime = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
        long startTime = startLocalTime.toEpochSecond(ZoneOffset.UTC);
        System.out.println(startTime);
        LocalDateTime now = LocalDateTime.now();

        String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd:HH:mm"));
        System.out.println(date);
    }
}
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/8qB6W7xRjffm7WI3qaO_zw