6位顺序号生成_基于redis生成全局唯一id

在集群环境中,为了生成全局唯一的6位顺序号,本文介绍了利用Redis的单线程特性实现订单号生成。通过RedisAtomicLong进行原子自增,并结合日期字符串确保唯一性。测试表明,在108秒内成功生成并插入了10万个订单号,平均约1毫秒生成1笔订单。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ccf7cc72d99dc47db2970ee6a11e81aa.png

在应用服务器集群环境下,在单台集群下加锁不能保证生成id的唯一性。那么我们如何保证在集群环境下生成唯一id呢,办法有很多

1 uuid生成全球唯一id,生成方式简单粗暴,本地生成,没有网络开销,效率高;缺点长度较长,没有递增趋势性,不易维护,常用于生成token令牌。

2 zookeeper通过创建顺序节点生成全局id,在高并发场景下,性能不能很好。

3 mysql自带自增生成id,oracle可以用序列生成id,但在数据库集群环境下,扩展性不好。

4 基于雪花算法snowflake 生成全局id,本地生成,没有网络开销,效率高,但是依赖机器时钟。

5 基于redis单线程的特点生成全局唯一id,redis性能高,支持集群分片。

这里主要介绍redis生成全局唯一id的实现方案

核心代码

@Resourceprivate RedisTemplate<String,Serializable> redisTemplate;/** * 获取有过期时间的自增长ID * @param key* @param expireTime* @return*/public long generate(String key,Date expireTime) {
RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
Long expire = counter.getExpire();if(expire==-1){
counter.expireAt(expireTime);
}return counter.incrementAndGet();
}public String generateOrderId() {//生成id为当前日期(yyMMddHHmmss)+6位(从000000开始不足位数补0)
LocalDateTime now = LocalDateTime.now();
String orderIdPrefix = getOrderIdPrefix(now);//生成yyyyMMddHHmmss
String orderId = orderIdPrefix+String.format("%1$06d", generate(orderIdPrefix,getExpireAtTime(now)));return orderId;
}public static String getOrderIdPrefix(LocalDateTime now){return now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
}public Date getExpireAtTime(LocalDateTime now){
ZoneId zoneId = ZoneId.systemDefault();
LocalDateTime localDateTime = now.plusSeconds(20);
ZonedDateTime zdt = localDateTime.atZone(zoneId);
Date date = Date.from(zdt.toInstant());return date;
}

思路:日期(yyyyMMddHHmmss)+redis原子生成的数字(不足6位前面补0)

类似:20191206221953000001

理论上6位后缀支持每秒最多生成999999个订单号,具体可以根据业务调整日期格式或日期后面的位数。核心在于对象RedisAtomicLong (可以想下juc包下的AtomicLong),它对于同一个key会一直自增生成数字,这里我设置的key过期时间为20s,减轻redis的压力。

RedisAtomicLong的incrementAndGet方法源码,看下能大致明白,对于每个不同的key每次自增1,这个是由redis天然单线程保证的,一般不会出现重复的情况。

18e35cdf1aa8f46a8f3e7b8e4c96219c.png

下面启动redis,mysql服务器,应用服务器,用jmeter做个小小的测试:发送10万个请求

c8493217eef1a134f67dea8f319a9357.png

期间报错过几次,经过调大jmeter堆内存顺利通过测试,测试代码

2b05bf8c8044e1900b7b9181bdf1cfd5.png

0ed2f1c217f714ec78899b6f05930576.png
可以看到总记录数为10万

order_id做了唯一索引,重复会报错

d103da4dbc0a56882d86d92dac5163db.png

e75069340242bf8cd6a5865ac61448cc.png

最大时间:2019-12-07 01:08:23,最最小时间:2019-12-07 01:06:35

在108秒内,在个人pc机上生成了10万个id并插入数据库

108/10万大约1毫秒完成1笔订单,redis性能还是可以的。

完结,有错误之处,望大佬指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值