概述
SnowFlake算法是Twitter设计的一个可以在分布式系统中生成唯一的ID的算法,它可以满足Twitter每秒上万条消息ID分配的请求,这些消息ID是唯一的且有大致的递增顺序。
原理
SnowFlake算法产生的ID是一个64位的整型,64个bit位被分成4段:
42--5--5--12
42位时间戳部分,这个是毫秒级的时间,一般实现上不会存储当前的时间戳,而是时间戳的差值(当前时间-固定的开始时间),这样可以使产生的ID从更小值开始;41位(第一位是符号位)的时间戳可以使用69年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年;
5位数据中心序号标识
5位workerid标识,每个部署节点应有唯一的workerid标识
12位序列号部分,支持同一毫秒内同一个节点可以生成4096个ID;
SnowFlake算法生成的ID大致上是按照时间递增的,用在分布式系统中时,需要注意数据中心标识和部署节点必须唯一,这样就能保证每个节点生成的ID都是唯一的。
这个方案是Tweet提出,比较适合Tweet这种顶级的互联网公司,对于中小型互联网公司来说,还是不太适合的,理由如下:
因此对于云原生(cloud native)的应用,同类服务我们要追求镜像唯一,配置尽量精简,且尽量消除启动环境变量和application.yml外的配置文件的读取。
改进方案:
1. 64位long型4段分为3段,去除datacenter id,10个bit全部赋予worker id
2. workerid无需指定,由zookeeper 临时有序类节点(EPHEMERAL_SEQUENTIAL)分配,具体的算法为:
SnowFlake算法是Twitter设计的一个可以在分布式系统中生成唯一的ID的算法,它可以满足Twitter每秒上万条消息ID分配的请求,这些消息ID是唯一的且有大致的递增顺序。
原理
SnowFlake算法产生的ID是一个64位的整型,64个bit位被分成4段:
42--5--5--12
42位时间戳部分,这个是毫秒级的时间,一般实现上不会存储当前的时间戳,而是时间戳的差值(当前时间-固定的开始时间),这样可以使产生的ID从更小值开始;41位(第一位是符号位)的时间戳可以使用69年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年;
5位数据中心序号标识
5位workerid标识,每个部署节点应有唯一的workerid标识
12位序列号部分,支持同一毫秒内同一个节点可以生成4096个ID;
SnowFlake算法生成的ID大致上是按照时间递增的,用在分布式系统中时,需要注意数据中心标识和部署节点必须唯一,这样就能保证每个节点生成的ID都是唯一的。
这个方案是Tweet提出,比较适合Tweet这种顶级的互联网公司,对于中小型互联网公司来说,还是不太适合的,理由如下:
1. 中小型的互联网公司服务一般部署在同个数据中心,要么在阿里云上,要么腾讯云上,因此数据中心序号可以去除。
2. 对于云原生的应用,同类服务要求部署docker镜像是完全一致的,那么workerid只能在docker启动时环境变量中指定,或者在外部配置文件中指定后让docker启动后读取,每次部署都要指定不一样的workerid,人工操作多了难免遗漏,以致不同的节点拥有相同的workerid,带来潜在的风险。因此对于云原生(cloud native)的应用,同类服务我们要追求镜像唯一,配置尽量精简,且尽量消除启动环境变量和application.yml外的配置文件的读取。
改进方案:
1. 64位long型4段分为3段,去除datacenter id,10个bit全部赋予worker id
2. workerid无需指定,由zookeeper 临时有序类节点(EPHEMERAL_SEQUENTIAL)分配,具体的算法为:
- 读取一个父node下所有的EPHEMERAL_SEQUENTIAL型节点,并把节点中的值(整形)读取出来,放入一个SET中
- for i=0 i<1023 i++
- 在父node下创建一个新的EPHEMERAL_SEQUENTIAL,并把节点值设为刚选定workerid
代码如下:
private long getUniqueWorkerId() {
long ret