午夜的低语:探索情感与感官的极致边界
数据库主键id的生成方案在设计系统时非常关键既影响性能也影响分布式扩展能力。
下面给出5 种主流方案并结合 Spring Boot MyBatis MySQL 项目推荐最佳实践及示例代码。
常见主键生成方案对比方案类型示例优点缺点适用场景
自增主键AUTO_INCREMENTid BIGINT AUTO_INCREMENT简单、易用、顺序性好分布式环境易冲突、插入热点单节点系统、小型项目
UUID字符串id CHAR(
全局唯一查询慢、存储冗余大无需排序的全局唯一标识
雪花算法Snowflake IDlong id Snowflake.nextId();高性能、趋势递增实现复杂、时间依赖分布式系统
Redis / 数据库序列号从 Redis 或 DB 获取自增号全局唯
可控有外部依赖多系统共享ID
自定义混合ID时间戳 随机数例如20251025142312345可读性好可能重复需控制临时或日志型记录✅
推荐方案Spring Boot MyBatis MySQL建议使用雪花算法Snowflake ID MyBatis 自动生成主键这样既不依赖 MySQL 自增可分库分表不会发生 ID 冲突效率极高ID 可作为时间序列排序。
✅
实现方案雪花算法版本1️⃣ 新建工具类SnowflakeIdGenerator.javapackage com.example.qrcode.util; /** * 雪花算法ID生成器 * 64位ID结构如下 * 1bit 符号位 41bit 时间戳 10bit 机器ID 12bit 序列号 */ public class SnowflakeIdGenerator { // 起始时间戳自定义纪元 private static final long START_STAMP 1672531200000L; //
// 每部分占位 private static final long SEQUENCE_BIT 12; // 序列号占12位 private static final long MACHINE_BIT 10; // 机器ID占10位 // 最大值 private static final long MAX_MACHINE_NUM ~(-1L MACHINE_BIT); private static final long MAX_SEQUENCE ~(-1L SEQUENCE_BIT); // 偏移量 private static final long MACHINE_LEFT SEQUENCE_BIT; private static final long TIMESTAMP_LEFT SEQUENCE_BIT MACHINE_BIT; private long machineId; // 机器ID private long sequence 0L; private long lastStamp -1L; public SnowflakeIdGenerator(long machineId) { if (machineId MAX_MACHINE_NUM || machineId
{ throw new IllegalArgumentException(机器ID超出范围); } this.machineId machineId; } // 获取下一个ID public synchronized long nextId() { long currStamp System.currentTimeMillis(); if (currStamp lastStamp) { throw new RuntimeException(时钟回拨拒绝生成ID); } if (currStamp lastStamp) { sequence (sequence
MAX_SEQUENCE; if (sequence 0L) { currStamp waitNextMillis(currStamp); } } else { sequence 0L; } lastStamp currStamp; return (currStamp - START_STAMP) TIMESTAMP_LEFT // 时间部分 | (machineId MACHINE_LEFT) // 机器部分 | sequence; // 序列部分 } private long waitNextMillis(long currStamp) { while (currStamp lastStamp) { currStamp System.currentTimeMillis(); } return currStamp; } }2️⃣ 在 Service 中使用package com.example.qrcode.service; import com.example.qrcode.entity.QrCodeRecord; import com.example.qrcode.mapper.QrCodeMapper; import com.example.qrcode.util.QrCodeUtil; import com.example.qrcode.util.SnowflakeIdGenerator; import org.springframework.stereotype.Service; Service public class QrCodeService { private final QrCodeMapper qrCodeMapper; private final SnowflakeIdGenerator idGenerator new SnowflakeIdGenerator(1L); public QrCodeService(QrCodeMapper qrCodeMapper) { this.qrCodeMapper qrCodeMapper; } public QrCodeRecord createAndSave(String content) throws Exception { byte[] imageBytes QrCodeUtil.generateQrAsBytes(content, 300,
; QrCodeRecord record new QrCodeRecord(); record.setId(idGenerator.nextId()); record.setContent(content); record.setImage(imageBytes); qrCodeMapper.insert(record); return record; } }3️⃣ 数据库表中改为手动ID插入CREATE TABLE qr_code_record ( id BIGINT PRIMARY KEY COMMENT 雪花算法ID, content VARCHAR(
NOT NULL, image LONGBLOB NOT NULL, created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP );✅
其他备选方案简略
MySQL 自增主键id BIGINT PRIMARY KEY AUTO_INCREMENT简单直接适合单机。
UUID 方案record.setId(UUID.randomUUID().toString());表结构id CHAR(
PRIMARY KEY但效率不如 Long 型。
Redis 全局序列号Long id redisTemplate.opsForValue().increment(global:qr:id);✅
推荐结论场景推荐方案单体应用、小项目AUTO_INCREMENT分布式系统、微服务✅雪花算法 (Snowflake)跨系统全局唯一IDRedis 序列 或 UUID临时或可读性强 ID时间戳 随机数拼接
玖辛奈穿黑白双煞的背景故事和故事-玖辛奈穿黑白双煞的背景故事和故事应用