1. 数据库主键自增
1.1 实现方案
通过创建表时,设置数据库主键自增
alter table sec_user modify id integer auto_increment ;
1.2 优缺点
优点: 依赖于数据库自身不需要其他资源;ID号单调自增,可以实现一些对ID有特殊要求的业务
缺点: 强依赖DB,当DB异常时整个系统不可用; 一致性难以保证:主从复制可增加可用性,但数据一致性在特殊情况下难保证:主从切换时的不一致可能会导致重复发号 ID发号性能瓶颈限制在单台MySQL的读写性能 id单调递增,规律性较强,存在安全风险。
2.UUID
2.1 实现方案
UUID由以下几部分的组合: (1)当前日期和时间。 (2)时钟序列。 (3)全局唯一的IEEE机器识别号,如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。 Java API实现:
UUID.randomUUID();
格式: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12)
样例: 550e8400-e29b-41d4-a716-446655440000
2.2 优缺点
优点: 1)简单,代码方便。 2)生成ID性能非常好,基本不会有性能问题,本地生成,没有网络消耗。 3)全球唯一,在遇见数据迁移,系统数据合并,或者数据库变更等情况下,可以从容应对
缺点: 1)生成的ID为32位128个字节的 字符串类型,存储占用比较大。 2)生成的ID为字符串类型,如果作为主键存储在数据库时,会导致数据库索引频繁重建 3)字符串类型查询效率较低。 4)信息不安全,基于MAC地址生成UUID的算法可能会造成MAC地址泄露,这个漏洞曾被用于寻找梅丽莎病毒的制作者位置。
3. 雪花算法(SnowFlake)
3.1 实现方案
组成部分: 符号位:1bit,正数永远为0 时间戳:41bit,精确到毫秒级别 机器标识:10bit,前5bit为机房标识,后5bit为机器标识。 自定义序列 :12bit,可以每一毫秒生成2^12个id
3.2 优缺点
优点: 1)简单高效,生成速度快。 2)时间戳在高位,自增序列在低位,整个ID是趋势递增的,按照时间有序递增。 3)灵活度高,可以根据业务需求,调整bit位的划分,满足不同的需求。
缺点: 1)依赖机器的时钟,如果服务器时钟回拨,会导致重复ID生成。 2)在分布式环境上,每个服务器的时钟不可能完全同步,有时会出现不是全局递增的情况。
4. 基于 Redis自增方案
4.1 实现方案
组成部分: 符号位:1bit,正数永远为0 时间戳:31bit,秒级 自定义序列:32bit
@Component
public class RedisIDWorker {
@Autowired
private StringRedisTemplate stringRedisTemplate;
private static final long TIME_STAMP = 1650727974L;
public long nextId(String keyPrefix) {
LocalDateTime localDateTime = LocalDateTime.now();
long nowTimeStamp = localDateTime.toEpochSecond(ZoneOffset.UTC);
long timeStamp = nowTimeStamp - TIME_STAMP;
String currentDate = localDateTime.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
Long increment = stringRedisTemplate.opsForValue().increment(keyPrefix + ":" + currentDate);
return (timeStamp << 31) ^ increment;
}
}
4.2 优缺点
优点: 1)不依赖于数据库,灵活方便,且性能优于数据库。 2)数字ID天然排序,对分页或者需要排序的结果很有帮助
缺点: 1)如果系统中没有Redis,还需要引入新的组件,增加系统复杂度。 2)需要编码和配置的工作量比较大。 3)Redis是单线程的,若造成阻塞,则会引发高并发问题,需要处理好集群与主从关系
|