27. 分布式 ID 生成
27.1 为什么需要分布式 ID
-
全局唯一性
: 不能出现重复的 ID 号, 既然是唯一标识, 这是最基本的要求。 -
趋势递增
: 在 MySQL InnoDB 引擎中使用的是聚集索引, 由于多数 RDBMS 使用 B-tree 的数据结构来存储索引数据, 在主键的选择上面我们应该尽量使用有序的主键保证写入性能。 -
单调递增
: 保证下一个 ID 一定大于上一个 ID, 例如事务版本号, IM 增量消息, 排序等特殊需求。 -
信息安全
: 如果 ID 是连续的, 恶意用户的扒取工作就非常容易做了, 直接按照顺序下载指定 URL 即可; 如果是订单号就更危险了, 竞对可以直接知道我们一天的单量。 所以在一些应用场景下, 会需要 ID 无规则, 不规则。
27.2 分布式 ID 有哪些
常见的分布式 ID 有 连续 GUID
、短 ID
、雪花算法 ID
。
27.3 如何使用
27.3.1 连续 GUID
方式
- 静态
IDGen
方式
var guid = IDGen.NextID();
// 还可以配置更多参数
var guid2 = IDGen.NextID(new SequentialGuidSettings { LittleEndianBinary16Format = true })); // SequentialGuidSettings 参数取决于你的分布式ID的实现
特别提醒
如果在循环中使用 IDGen
静态类方式,性能最差,原因是底层不断解析服务。如果非循环中,性能等于下面两种用法。
IDistributedIDGenerator
注入方式 推荐
private readonly IDistributedIDGenerator _idGenerator;
public AppServices(IDistributedIDGenerator idGenerator)
{
_idGenerator = idGenerator;
var guidObject = _idGenerator.Create();
}
SequentialGuidIDGenerator
方式
var idGen = new SequentialGuidIDGenerator();
var guid = idGen.Create();
// 更多参数
var idGen2 = new SequentialGuidIDGenerator();
var guid2 = idGen2.Create(new SequentialGuidSettings { LittleEndianBinary16Format = true });
27.3.2 短 ID
短 ID
按道理不应该放在分布式 ID 生成这个章节,它的作用用途常用于并发不强的内部系统中,比如 任务ID
,Issue 编号
等等。
var shortid = ShortIDGen.NextID(); // 生成一个包含数字,字母,不包含特殊符号的 8 位短id
// 添加更多配置
var shortid = ShortIDGen.NextID(new GenerationOptions {
UseNumbers = false, // 不包含数字
UseSpecialCharacters = true, // 包含特殊符号
Length = 8// 设置长度,注意:不设置次长度是随机长度!!!!!!!
});
// 自定义生成短 ID 参与运算字符
string characters = "ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ①②③④⑤⑥⑦⑧⑨⑩⑪⑫"; //whatever you want;
ShortIDGen.SetCharacters(characters);
// 自定义随机数(for)步长
int seed = 1939048828;
ShortIDGen.SetSeed(seed);
// 重载所有自定义配置
ShortIDGen.Reset();
27.3.3 雪花算法 ID
Furion
在最新的 2.1 +
版本移除了雪花算法 ID
功能,原因是:
目前,雪花算法 ID
使用频率不高,而且实现 雪花算法 ID
的方式也是千差万别,所以框架移除该功能,采用拓展或自集成方式。
27.4 反馈与建议
与我们交流
给 Furion 提 Issue。