erlang:make_ref/0与erlang:unique_integer选型规则及适用场景咨询
Erlang 中
erlang:make_ref/0与erlang:unique_integer/0,1选型指南 通用选型经验法则
没有复杂的玄学规则,按使用场景直接套用即可:
- 短生命周期、仅在Erlang生态内部(单节点/同个分布式Erlang集群)流转的临时标识,比如请求关联ID、消息匹配标签、进程内临时键值,优先用
erlang:make_ref/0 - 需要整数类型、要跨系统交互、要持久化存储、或者需要单调递增特性的标识,优先用
erlang:unique_integer/1
短生命周期的消息、请求处理场景下把make_ref换成unique_integer通常不会出问题,这是客观事实,二者在这类场景下本来就没有本质功能差异,只是初始设计定位不同。
核心差异对比
执行速度
二者都是O(1)的原子操作,单进程每秒生成量都能达到千万级,常规业务场景完全感知不到性能差距。只有在极端压测(单进程每秒生成百万级以上标识)下,erlang:unique_integer([positive])因为不需要做引用类型的封装,会比make_ref/0快3%~8%,这个差异对99%的业务来说都不值得作为选型依据。
唯一性保障
二者的唯一性边界有明确区别,不要超范围使用:
erlang:make_ref/0生成的是Erlang专属的reference类型,仅保证单个Erlang节点当前运行周期内全局唯一,分布式集群下因为ref值自带节点标识片段,不同节点生成的ref也不会冲突。但节点重启后,之前生成过的ref值可能重复;同时ref没有统一的跨语言序列化标准,跨系统传输时很容易因为不同SDK的序列化规则差异出现值不一致的问题。erlang:unique_integer生成的是原生整数类型:- 不传参数调用时,保证当前节点运行周期内生成的值全局唯一,性能最优
- 传入
[monotonic, positive]参数时,生成的正整数不仅唯一,还严格单调递增,适合做版本号、顺序偏移量
默认配置下它的唯一性范围同样是单节点当前运行周期,跨节点、节点重启后如果没有额外拼接标识,也可能出现重复。
长生命周期/跨系统场景选型结论
这类场景优先选erlang:unique_integer/1,没有太多争议:
- 整数是所有编程语言、存储系统都原生支持的基础类型,序列化、反序列化、存储、传输都没有兼容问题,不管是存数据库、返回给前端、对接第三方服务,都不需要做特殊的类型适配,不会出现ref类型跨端解析失败的问题
- 扩展全局唯一的成本极低:只要把节点ID、节点启动纪元值拼在生成的整数高位,就能得到跨节点、跨重启周期都不重复的长生命周期ID,完全适配持久化需求
- 单调递增的特性可以直接用作数据库主键、消息队列偏移量,不需要额外转换排序规则
make_ref/0天生不适合这类场景:它是Erlang专属类型,没有跨系统统一的表示标准,节点重启后存在重复概率,且ref值本身没有顺序属性,存到数据库后无法做范围查询、排序,完全没必要在这类场景硬用。
踩坑提醒:不要直接把默认配置下生成的
unique_integer值当分布式全局唯一ID用,它本身不带节点标识和重启校验位,跨节点写入、节点重启后都可能出现主键冲突。
内容的提问来源于stack exchange,提问作者ITChap
相关产品推荐
相关产品推荐

