ID生成器
这页对应 3.x 里的 ID 生成使用方式,核心组件是 ID 生成器(Aegis.IdGenerator)。如果模板编号需要在多实例间共享流水号,还要继续接 Redis ID 生成提供程序(Aegis.IdGenerator.Provider.Redis)。
先记住这组能力的边界
当前 ID 生成体系主要分成两类:
- 雪花 ID:返回
long - 模板 ID:返回带业务格式的字符串
最简单的判断方式是:
- 只要唯一数字主键,用雪花 ID
- 只要带前缀、日期、流水号的业务单号,用模板 ID
最常用的接入方式
只要雪花 ID
{
"Components": {
"Services": [
"IdGenerator.SnowflakeId"
]
}
}
雪花 ID 和模板 ID 都要
{
"Components": {
"Services": [
"IdGenerator"
]
}
}
雪花 ID 怎么配
{
"IdGenerator": {
"WorkerId": 2,
"WorkerIdLength": 5,
"IndexLength": 8
}
}
这几个配置项分别是什么意思
| 配置项 | 作用 |
|---|---|
WorkerId | 当前节点编号 |
WorkerIdLength | 节点编号位数 |
IndexLength | 同一时间窗口内的流水号位数 |
WorkerIdProvider | WorkerId 提供器类型名 |
StartTimeStamp | 雪花算法起始时间 |
最常见的使用方式
public class SnowflakeService
{
private readonly IIdGenerator _idGenerator;
public SnowflakeService(IIdGenerator idGenerator)
{
_idGenerator = idGenerator;
}
public long CreateId()
{
return _idGenerator.NextId();
}
}
使用雪花 ID 时最重要的一条规则
多实例场景下,每个实例的 WorkerId 都必须唯一。
这一点如果配错,后面的唯一性就没有保障。
模板 ID 怎么接
模板 ID 至少需要三样东西:
- 模板能力本身
- 模板提供者
- 如果是多实例,再补 Redis 序号容器
第一步:启用模板能力
{
"Components": {
"Services": [
"IdGenerator.TemplateId"
]
}
}
如果你已经启用了总入口 IdGenerator,这一步可以不用再单独配。
第二步:注册模板提供者
services.AddIdTemplateProvider<TemplateProvider>();
第三步:实现模板提供者
public class TemplateProvider : IIdTemplateProvider
{
public async Task<IdTemplate[]> GetIdTemplates()
{
var template = new IdTemplate
{
Key = "A1",
PaddingChar = '0',
DateReset = true,
CanReturn = true,
FormatString = "Test{Date}{SerialNum}",
SerialNumLength = 6
};
return new[] { template };
}
}
IdTemplate 最常见字段怎么理解
| 字段 | 作用 |
|---|---|
Key | 模板键 |
FormatString | 编号格式,如 Test{Date}{SerialNum} |
SerialNumLength | 流水号长度 |
PaddingChar | 流水号填充字符 |
DateReset | 是否按日期重置流水 |
CanReturn | 是否允许归还编号 |
MinSerialNum | 最小流水号 |
MaxSerialNum | 最大流水号 |
RecoveryTime | 归还时间窗口 |
模板 ID 怎么用
获取单个编号
var id = _templateIdGenerator.GetId("A1");
批量获取编号
var ids = _templateIdGenerator.GetIds("A1", 30);
归还和确认编号
_templateIdGenerator.ReleaseId("A1", id);
_templateIdGenerator.ConfirmId("A1", id);
_templateIdGenerator.ConfirmIds("A1", ids);
动态新增和移除模板
_idTemplateManager.Add(new IdTemplate
{
Key = "A1",
CanReturn = true,
FormatString = "ORD{Date}{SerialNum}",
DateReset = true,
PaddingChar = '0',
SerialNumLength = 6
});
_idTemplateManager.Remove("A1");
什么情况下要继续接 Redis 容器
只要进入下面这些场景,就建议把模板流水号切到 Redis:
- 多实例部署
- 模板编号要跨实例共享
- 需要归还和重用编号
- 不希望单机重启后序号行为失控
最常见接法如下:
services.AddRedisSource<AegisRedisSource>(
ConfigManager.Get<RedisOptions>("Redis"));
services.AddIdRedisContainer<AegisRedisSource>();
services.AddIdTemplateProvider<TemplateProvider>();
接入完成后怎么确认成功
你至少应该确认这些点:
Component.deps.json已启用正确的 ID 生成组件声明- 雪花模式下可以稳定注入
IIdGenerator - 模板模式下可以稳定注入
ITemplateIdGenerator - 模板
Key能找到对应规则 - 多实例场景下模板编号不会重复
常见问题
为什么只能拿到雪花 ID,拿不到模板能力
通常是只启用了 IdGenerator.SnowflakeId,没有启用 IdGenerator 或 IdGenerator.TemplateId。
为什么模板已经注册了,但 GetId("A1") 还是失败
优先检查:
- 模板提供者是否真的注册成功
- 返回的
Key是否就是A1 - 当前模板能力是否已经启用
为什么模板编号在多实例下重复或错乱
这通常说明模板流水号还没有切到 Redis 容器。