原文连接:何晓东 博客html
文章起源于 康神交流群的 panda大佬和boss li关于发号器的一些交流,特此感谢让咱们学到了新知识。
在分布式系统中,常常须要对大量的数据、消息、http 请求等进行惟一标识,例如:对于分布式系统,服务间相互调用须要惟一标识,调用链路分析,日志追踪的时候须要使用这个惟一标识。此时须要一个全局惟一的 ID。mysql
持久化git
要知足长期全局惟一,持久化是必须的,确定不能让已经使用的再次产生一遍,同时须要强一致性。可用选择存储在 Redis 或者 Etcd 中。
高可用github
这个时候须要提供发号器服务的机器主从同步,可以在主服务器宕机的时候,自动选择从服务器,切换过程当中,发号器生成的 ID 可能不连续,服务正常就能够。
其余特性算法
主要是看具体业务了,须要认证和权限控制都是可选的,可用在请求层限制来源 IP,只容许固定的 IP 访问。
UUID 是 Universally Unique Identifier 的缩写,它是在必定的范围内(从特定的名字空间到全球)惟一的机器生成的标识符,UUID 是16字节128位长的数字,一般以36字节的字符串表示,好比:3F2504E0-4F89-11D3-9A0C-0305E82C3301。sql
UUID经由必定的算法机器生成,为了保证 UUID 的惟一性,规范定义了包括网卡 MAC 地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素,以及从这些元素生成 UUID 的算法。UUID 的复杂特性在保证了其惟一性的同时,意味着只能由计算机生成。数据库
优缺点: 本地生成,性能高,延迟低,位数长,不适用看成索引字段,同时是无序的,难以根据特征分析趋势。segmentfault
snowflake是twitter开源的分布式ID生成算法,其核心思想为,一个long型的ID:
41bit做为毫秒数 - 10bit做为机器编号 - 12bit做为毫秒内序列号
算法单机每秒内理论上最多能够生成1000*(2^12),也就是400W的ID,
服务器
优缺点: 整个 ID 都是自增的,这个很是适合查看趋势,同时生成不依赖于第三方系统,可靠性很高,可调整性也很高。缺点就是严重依赖机器时钟。异步
字段设置 auto_increment_increment
和 auto_increment_offset
来保证 ID 自增,每次业务使用下列 SQL 读写 MySQL 获得 ID。
begin; REPLACE INTO Tickets64 (stub) VALUES ('a'); SELECT LAST_INSERT_ID(); commit;
为了保证高可用,须要有多台 MySQL 机器,也须要为每台机器设置不一样的自增起始值和步长,例如:
# TicketServer1: auto-increment-increment = 2 auto-increment-offset = 1 # TicketServer2: auto-increment-increment = 2 auto-increment-offset = 2
优缺点: 简单可靠,成本很小,由专业 DBA 进行维护就能够的。ID 单调递增,有合适的业务是最好的。缺点就是强依赖于数据库,修改起点和步长优势困难,同时也须要额外保证数据库的稳定可用。每次请求都去额外读写数据库的状况下,形成数据库压力很大,须要消耗不少资源。
以上就是最经常使用的三种全局惟一 ID 生成方案,采用较多的是类 snowflake 的方案,若是请求数列不是很高,能够调低时间的精度等,灵活性很高。生成的 ID 时间趋势自增,甚至能够用来作索引字段,占用空间较小。后期对数据进行分析的时候也很方便。
类 snowflake 的方案,会采用请求时生成的方式,没法提早生成。
基于 MySQL 的发号器,或者 uuid 模式的,可用提早生成一大批数据,根据业务去定生成数量,放到内存,MQ 或者 Redis List中,业务申请惟一 ID 的时候,直接从其中弹一个出来。同时加一个异步定时任务,固定时间计算一下队列中剩余的惟一 ID 数量,数量不足时及时的再次生成一大批,加入到备选队列。
Go snowflake的demo:
参考文章:
一如既往,推荐几个 高质量课程,你学到新东西,我赚点佣金,你们都是赢家。