简历_利用优化的Redis自增ID策略天生分布式环境下全局唯一ID,用于用户上传
系列博客目次Why
我们必要设置全局唯一ID。原因:当用户抢购时,就会天生订单并保存到tb_voucher_order这张表中,而订单表如果利用数据库自增ID就存在一些问题。
问题:id的规律性太显着、受单表数据量的限制。以是在自己的项目中,针对上传的数据的ID的天生也可以利用全局唯一ID。表中有ID,属性范例(文本、音频、图像)以及存储位置,文件名(文件名由ID+原始文件名作为后缀构成)。
多种ID比如用户ID,订单ID。
全局ID天生器,是一种在分布式系统下用来天生全局唯一ID的工具,一般要满意下列特性:高可用、唯一性、高性能、递增性、安全性。
Redis自增ID策略
为了增加ID的安全性,我们可以不直接利用Redis自增的数值,而是拼接一些其它信息:
https://i-blog.csdnimg.cn/direct/88f79e58dc724852a90a4ce93f76324a.png
ID的构成部分:
[*]符号位:1bit,永久为0
[*]时间戳:31bit,以秒为单元,可以利用69年
[*]序列号:32bit,秒内的计数器,支持每秒产生2^32个不同ID
package com.hmdp.utils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
@Component
public class RedisIdWorker {
/**
* 开始时间戳
*/
private static final long BEGIN_TIMESTAMP = 1640995200L;
/**
* 序列号的位数
*/
private static final int COUNT_BITS = 32;
private 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;
}
}
利用的示例代码如下:
// 7.创建订单
VoucherOrder voucherOrder = new VoucherOrder();
// 7.1.订单id
long orderId = redisIdWorker.nextId("order");
voucherOrder.setId(orderId);
// 7.2.用户id
voucherOrder.setUserId(userId);
// 7.3.代金券id
voucherOrder.setVoucherId(voucherId);
save(voucherOrder);
// 7.返回订单id
return Result.ok(orderId);
每天一个key,方便统计订单量
ID 的构造是 :时间戳 + 计数器
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]