当前位置: 首页 > news >正文

受欢迎的网站建设公司外贸接单网站

受欢迎的网站建设公司,外贸接单网站,日本网站开发工程师工资,网页设计什么主题好Snowflake,雪花算法是由Twitter开源的分布式ID生成算法,以划分命名空间的方式将 64-bit位分割成多个部分,每个部分代表不同的含义。这种就是将64位划分为不同的段,每段代表不同的涵义,基本就是时间戳、机器ID和序列数。…
Snowflake,雪花算法是由Twitter开源的分布式ID生成算法,以划分命名空间的方式将 64-bit位分割成多个部分,每个部分代表不同的含义。这种就是将64位划分为不同的段,每段代表不同的涵义,基本就是时间戳、机器ID和序列数。为什么如此重要?因为它提供了一种ID生成及生成的思路,当然这种方案就是需要考虑时钟回拨的问题以及做一些 buffer的缓冲设计提高性能。

雪花算法-Snowflake

Snowflake,雪花算法是由Twitter开源的分布式ID生成算法,以划分命名空间的方式将 64-bit位分割成多个部分,每个部分代表不同的含义。而 Java中64bit的整数是Long类型,所以在 Java 中 SnowFlake 算法生成的 ID 就是 long 来存储的。

  • 第1位占用1bit,其值始终是0,可看做是符号位不使用。

  • 第2位开始的41位是时间戳,41-bit位可表示2^41个数,每个数代表毫秒,那么雪花算法可用的时间年限是(1L<<41)/(1000L360024*365)=69 年的时间。

  • 中间的10-bit位可表示机器数,即2^10 = 1024台机器,但是一般情况下我们不会部署这么台机器。如果我们对IDC(互联网数据中心)有需求,还可以将 10-bit 分 5-bit 给 IDC,分5-bit给工作机器。这样就可以表示32个IDC,每个IDC下可以有32台机器,具体的划分可以根据自身需求定义。

  • 最后12-bit位是自增序列,可表示2^12 = 4096个数。

这样的划分之后相当于在一毫秒一个数据中心的一台机器上可产生4096个有序的不重复的ID。但是我们 IDC 和机器数肯定不止一个,所以毫秒内能生成的有序ID数是翻倍的。

Snowflake 的Twitter官方原版是用Scala写的,对Scala语言有研究的同学可以去阅读下,以下是 Java 版本的写法。

package com.jajian.demo.distribute;/*** Twitter_Snowflake<br>* SnowFlake的结构如下(每部分用-分开):<br>* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>* 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>* 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)* 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>* 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>* 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>* 加起来刚好64位,为一个Long型。<br>* SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。*/
public class SnowflakeDistributeId {// ==============================Fields===========================================/*** 开始时间截 (2015-01-01)*/private final long twepoch = 1420041600000L;/*** 机器id所占的位数*/private final long workerIdBits = 5L;/*** 数据标识id所占的位数*/private final long datacenterIdBits = 5L;/*** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数)*/private final long maxWorkerId = -1L ^ (-1L << workerIdBits);/*** 支持的最大数据标识id,结果是31*/private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);/*** 序列在id中占的位数*/private final long sequenceBits = 12L;/*** 机器ID向左移12位*/private final long workerIdShift = sequenceBits;/*** 数据标识id向左移17位(12+5)*/private final long datacenterIdShift = sequenceBits + workerIdBits;/*** 时间截向左移22位(5+5+12)*/private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;/*** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)*/private final long sequenceMask = -1L ^ (-1L << sequenceBits);/*** 工作机器ID(0~31)*/private long workerId;/*** 数据中心ID(0~31)*/private long datacenterId;/*** 毫秒内序列(0~4095)*/private long sequence = 0L;/*** 上次生成ID的时间截*/private long lastTimestamp = -1L;//==============================Constructors=====================================/*** 构造函数** @param workerId     工作ID (0~31)* @param datacenterId 数据中心ID (0~31)*/public SnowflakeDistributeId(long workerId, long datacenterId) {if (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));}if (datacenterId > maxDatacenterId || datacenterId < 0) {throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));}this.workerId = workerId;this.datacenterId = datacenterId;}// ==============================Methods==========================================/*** 获得下一个ID (该方法是线程安全的)** @return SnowflakeId*/public synchronized long nextId() {long timestamp = timeGen();//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常if (timestamp < lastTimestamp) {throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}//如果是同一时间生成的,则进行毫秒内序列if (lastTimestamp == timestamp) {sequence = (sequence + 1) & sequenceMask;//毫秒内序列溢出if (sequence == 0) {//阻塞到下一个毫秒,获得新的时间戳timestamp = tilNextMillis(lastTimestamp);}}//时间戳改变,毫秒内序列重置else {sequence = 0L;}//上次生成ID的时间截lastTimestamp = timestamp;//移位并通过或运算拼到一起组成64位的IDreturn ((timestamp - twepoch) << timestampLeftShift) //| (datacenterId << datacenterIdShift) //| (workerId << workerIdShift) //| sequence;}/*** 阻塞到下一个毫秒,直到获得新的时间戳** @param lastTimestamp 上次生成ID的时间截* @return 当前时间戳*/protected long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}/*** 返回以毫秒为单位的当前时间** @return 当前时间(毫秒)*/protected long timeGen() {return System.currentTimeMillis();}
}

测试的代码如下

public static void main(String[] args) {SnowflakeDistributeId idWorker = new SnowflakeDistributeId(0, 0);for (int i = 0; i < 1000; i++) {long id = idWorker.nextId();
//      System.out.println(Long.toBinaryString(id));System.out.println(id);}
}

雪花算法提供了一个很好的设计思想,雪花算法生成的ID是趋势递增,不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的,而且可以根据自身业务特性分配bit位,非常灵活

但是雪花算法强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。如果恰巧回退前生成过一些ID,而时间回退后,生成的ID就有可能重复。官方对于此并没有给出解决方案,而是简单的抛错处理,这样会造成在时间被追回之前的这段时间服务不可用。

很多其他类雪花算法也是在此思想上的设计然后改进规避它的缺陷,后面介绍的百度 UidGenerator 和 美团分布式ID生成系统 Leaf 中snowflake模式都是在 snowflake 的基础上演进出来的。

其它相关算法

在如下文章中已经包含了所有主流的全局唯一ID实现方案:

  • 分布式系统 - 全局唯一ID实现方案

这里给出相关的链接:

  • 为什么需要全局唯一ID

  • UUID

  • 数据库生成

  • 使用redis实现

  • 雪花算法-Snowflake

  • 百度-UidGenerator

  • DefaultUidGenerator 实现

  • CachedUidGenerator 实现

  • 美团Leaf

  • Leaf-segment 数据库方案

  • Leaf-snowflake方案

  • Mist 薄雾算法


整理好的Java面试资料,推荐阅读下载:

最全的java面试题库

Java核心知识点整理

http://www.mnyf.cn/news/40660.html

相关文章:

  • 网站建设公司价格真甲先生微信视频号怎么推广引流
  • 企业做淘宝客网站seo网页推广
  • 网站模板佳好乐云seo电商怎么做新手入门
  • 羊肉口报关做网站网上哪里可以免费打广告
  • 做物理的网站幽默软文经典案例300
  • 网站搭建的费用seo外包优化
  • 淘宝客导购网站最新中央人事任免
  • 西部数码网站管理助手serv-u默认密码石家庄关键词优化平台
  • 做北美市场的外贸网站刷关键词指数
  • 网站竞价推广2022年近期重大新闻事件
  • 公司官网建设哪家好app排名优化公司
  • 衢州网站建设需要多少费用哪里可以引流到精准客户呢
  • 影视传媒网站源码汕头网站建设公司
  • 重庆建设工程安全网什么是seo技术
  • 宁波产品网站设计模板注册推广赚钱一个10元
  • 东莞网站建设教程网络推广网站推广淘宝运营商
  • 绵阳网站建设价格如何自己做推广
  • 乐山市建设局网站前端优化
  • 刚做的网站怎么在百度上能搜到教育培训机构推荐
  • 沧州网站优化济南网站建设方案
  • 网站制作 意向单网络营销的内涵
  • 杭州网站建设公司联系方式互联网产品推广
  • 做服装最好的网站建设企业网站定制开发
  • python做的网站如何打开诊断网站seo现状的方法
  • 企业网站必须备案吗小学生简短小新闻摘抄
  • 前端个人网站模板汕头网页搜索排名提升
  • 邢台做wap网站找谁各类资源关键词
  • 网站开发 制作软文营销是什么
  • 为什么很多网站用php做百度提交网址入口
  • 制作自己网站有什么软件女教师遭网课入侵直播录屏曝