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

福州网站制作哪里有网站推广优化

福州网站制作,哪里有网站推广优化,遵义网站制作费用,深圳产品型网站建设以下是用Java实现的雪花算法代码示例,包含详细注释和异常处理: 代码下面有解析 public class SnowflakeIdGenerator {// 起始时间戳(2020-01-01 00:00:00)private static final long START_TIMESTAMP 1577836800000L;// 各部分…

以下是用Java实现的雪花算法代码示例,包含详细注释和异常处理:

代码下面有解析

public class SnowflakeIdGenerator {// 起始时间戳(2020-01-01 00:00:00)private static final long START_TIMESTAMP = 1577836800000L;// 各部分的位数private static final long DATA_CENTER_ID_BITS = 5L;  // 数据中心ID占5位private static final long WORKER_ID_BITS = 5L;       // 工作节点ID占5位private static final long SEQUENCE_BITS = 12L;       // 序列号占12位// 最大值计算(位运算)private static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS);// 左移位数private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;private static final long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATA_CENTER_ID_BITS;private final long dataCenterId;  // 数据中心IDprivate final long workerId;      // 工作节点IDprivate long sequence = 0L;       // 序列号private long lastTimestamp = -1L; // 上次生成时间/*** 构造函数* @param dataCenterId 数据中心ID (0~31)* @param workerId     工作节点ID (0~31)*/public SnowflakeIdGenerator(long dataCenterId, long workerId) {if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) {throw new IllegalArgumentException("DataCenter ID 超出范围");}if (workerId > MAX_WORKER_ID || workerId < 0) {throw new IllegalArgumentException("Worker ID 超出范围");}this.dataCenterId = dataCenterId;this.workerId = workerId;}/*** 生成下一个ID(线程安全)*/public synchronized long nextId() {long currentTimestamp = System.currentTimeMillis();// 时钟回拨检查if (currentTimestamp < lastTimestamp) {throw new RuntimeException("时钟回拨,拒绝生成ID");}if (currentTimestamp == lastTimestamp) {// 同一毫秒内序列号递增sequence = (sequence + 1) & MAX_SEQUENCE;if (sequence == 0) {// 当前毫秒序列号用完,等待下一毫秒currentTimestamp = waitNextMillis(lastTimestamp);}} else {// 新毫秒重置序列号sequence = 0L;}lastTimestamp = currentTimestamp;// 组合各部分生成IDreturn ((currentTimestamp - START_TIMESTAMP) << TIMESTAMP_SHIFT)| (dataCenterId << DATA_CENTER_ID_SHIFT)| (workerId << WORKER_ID_SHIFT)| sequence;}/*** 阻塞等待直到下一毫秒*/private long waitNextMillis(long lastTimestamp) {long currentTimestamp = System.currentTimeMillis();while (currentTimestamp <= lastTimestamp) {currentTimestamp = System.currentTimeMillis();}return currentTimestamp;}public static void main(String[] args) {// 示例用法SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1, 1);for (int i = 0; i < 10; i++) {System.out.println("生成的ID: " + idGenerator.nextId());}}
}

好的!我来用更简单的方式分步讲解雪花算法的分布式核心逻辑,以及Java代码的关键部分。


第一步:为什么需要分布式ID?

在单机系统中,可以用数据库自增ID。但在分布式系统中,多个节点同时生成ID时,自增ID会冲突。雪花算法通过结构划分,让每个节点独立生成全局唯一ID


第二步:雪花ID的结构(64位)

想象把64位的数字分成四个部分,像切蛋糕一样:

  1. 符号位(1位):固定为0,保证ID是正数(蛋糕边角料,几乎不用管)。
  2. 时间戳(41位):记录ID生成的时间(精确到毫秒),保证ID随时间递增。
  3. 机器ID(10位):分配给不同机器的编号,确保不同机器的ID不冲突。
  4. 序列号(12位):同一毫秒内,如果生成多个ID,用序列号区分。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


第三步:机器ID的分配(分布式核心)

问题:如果多台机器生成ID,如何确保它们的ID不重复?
解决方案:为每台机器分配一个唯一编号(比如:数据中心ID + 工作节点ID)。
示例:5位数据中心ID(031) + 5位工作节点ID(031) → 最多支持 32×32=1024 台机器。
分配方式:手动配置或通过ZooKeeper等工具动态分配。


第四步:Java代码关键点拆解

1. 定义各部分的位数
private static final long DATA_CENTER_ID_BITS = 5L;  // 数据中心ID占5位
private static final long WORKER_ID_BITS = 5L;       // 工作节点ID占5位
private static final long SEQUENCE_BITS = 12L;       // 序列号占12位
2. 计算最大值(防止溢出)
// 5位最大值是 2^5-1 = 31
private static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);
private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
3. 生成ID的核心逻辑
public synchronized long nextId() {long currentTimestamp = System.currentTimeMillis();// 1. 检查时钟回拨(时间不能倒流)if (currentTimestamp < lastTimestamp) {throw new RuntimeException("时钟回拨!");}// 2. 同一毫秒内生成多个IDif (currentTimestamp == lastTimestamp) {sequence++; // 序列号+1if (sequence > MAX_SEQUENCE) {// 当前毫秒的序列号用完了,等待下一毫秒currentTimestamp = waitNextMillis(lastTimestamp);sequence = 0;}} else {sequence = 0; // 新的一毫秒,序列号重置}lastTimestamp = currentTimestamp;// 3. 拼接各部分(位运算)return (时间戳部分) | (机器ID部分) | (序列号部分);
}
4. 位运算如何拼接?

假设时间差是 1000ms,数据中心ID=1,工作节点ID=1,序列号=0:

时间戳部分:1000ms << 22位(左移后占据高位)
机器ID部分:1 << 17位(左移后占据中间)
工作节点部分:1 << 12位(左移后占据中间)
序列号部分:0(占据最后12位)最终二进制:
0000000000000000000000011111101000 00001 00001 000000000000

第五步:分布式场景示例

机器A:数据中心ID=1,工作节点ID=1
机器B:数据中心ID=1,工作节点ID=2
机器C:数据中心ID=2,工作节点ID=1

同一毫秒内,三台机器生成的ID:

机器A:时间戳 | 1(数据中心) | 1(工作节点) | 序列号
机器B:时间戳 | 1(数据中心) | 2(工作节点) | 序列号
机器C:时间戳 | 2(数据中心) | 1(工作节点) | 序列号

即使时间戳和序列号相同,机器ID不同 → 最终ID不同!


第六步:常见问题解答

1. 为什么时间戳占41位?

• 41位二进制能表示的时间范围是 2^41 / 1000 / 3600 / 24 / 365 ≈ 69年
• 如果从2020年开始,可以用到2089年。

2. 时钟回拨怎么办?

原因:服务器时间被手动调整或NTP同步导致时间倒退。
处理:代码中直接抛出异常(生产环境可优化为等待时钟追上)。

3. 序列号为什么是12位?

• 12位支持每毫秒生成 4096个ID2^12 = 4096),足够大多数场景使用。


总结

雪花算法的分布式核心就是:

  1. 分蛋糕:把64位分成时间、机器ID、序列号。
  2. 唯一机器ID:确保不同机器的ID不冲突。
  3. 时间有序:时间戳保证ID整体递增,适合数据库索引。

代码中的位运算就像拼乐高积木,把时间、机器编号、序列号拼成一个完整的ID。你提到的这一点非常重要!这里涉及到位运算二进制补码的知识,我来详细拆解这个计算过程,保证彻底讲清楚。


问题聚焦

代码中的这两行:

private static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);
private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);

为什么 DATA_CENTER_ID_BITS = 5 时,MAX_DATA_CENTER_ID = 31?如何通过位运算得出这个结果?


第一步:理解二进制补码

在计算机中,负数用补码表示。例如:
-1 的二进制补码形式是:11111111 11111111 ... 11111111(64位全1)。


**第二步:分步计算 **~(-1L << 5)

DATA_CENTER_ID_BITS = 5 为例:

  1. **计算 **-1L << 5
    -1L 的二进制:11111111 11111111 ... 11111111(64位全1)。
    • 左移5位后:
11111111 11111111 ... 11111111 00000  
↑ 左侧丢弃5位,右侧补5个0

• 结果仍是一个负数(最高位是1)。

  1. 按位取反 ~ 操作
    • 对 111...11100000 取反:
00000000 00000000 ... 00000000 11111  
↑ 所有位取反(0变1,1变0)

• 此时最高位是0,表示正数。

  1. 转换为十进制
    • 二进制 000...0011111 的十进制是 2^4 + 2^3 + 2^2 + 2^1 + 2^0 = 31

通用公式

• 对于 n 位:~(-1L << n) = 2^n - 1
例如:
n=52^5-1=31
n=102^10-1=1023


为什么不用 2^n - 1 直接赋值?

代码中通过位运算动态计算最大值,有两个优点:

  1. 可读性:直接体现“用n位表示最大值”的逻辑。
  2. 可维护性:若未来调整位数(如改为6位),无需手动计算 2^6-1=63,代码自动适应。

代码中的验证逻辑

构造函数中检查数据中心ID和工作节点ID是否超过最大值:

public SnowflakeIdGenerator(long dataCenterId, long workerId) {if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) {throw new IllegalArgumentException("DataCenter ID 超出范围");}// 同理检查workerId
}

• 若传入 dataCenterId=32(超过31),会直接抛出异常,防止生成重复ID。


举例验证

假设 DATA_CENTER_ID_BITS = 3(最大值应为 2^3-1=7):

  1. -1L << 3111...11111111000(64位)。
  2. 取反后 → 000...00000000111(二进制7)。
  3. MAX_DATA_CENTER_ID = 7

总结

核心逻辑:通过左移和取反计算n位能表示的最大正整数。
位运算技巧:利用补码和位移动态计算最大值,避免硬编码。
设计意图:确保机器ID在指定范围内,防止分布式系统中ID冲突。好的!我再用一个更生活化的比喻和分步拆解,确保彻底讲明白这段代码的逻辑。


比喻:楼层与房间号

想象你要为一家全球连锁酒店设计房间号,规则如下:

  1. 酒店编号:区分不同国家/城市的酒店(如北京=01,上海=02)。
  2. 分店编号:同一城市的不同分店(如北京分店A=001,分店B=002)。
  3. 时间戳:记录房间分配的日期(如20231025)。
  4. 序列号:同一天内分配的房间顺序(如0001, 0002)。

最终房间号格式:时间戳 + 酒店编号 + 分店编号 + 序列号,例如:
20231025 01 001 0001 → 北京分店A在2023年10月25日分配的第1个房间。


对应雪花算法

将上述规则映射到雪花算法的64位ID:
时间戳:占据高位(相当于日期)。
数据中心ID(酒店编号):区分不同数据中心。
工作节点ID(分店编号):同一数据中心的不同机器。
序列号:同一毫秒内的顺序号。


代码逐行拆解

1. 定义左移位数
private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;
private static final long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATA_CENTER_ID_BITS;

作用:计算每个部分在二进制中的起始位置
示例(假设配置):
• 序列号占12位(SEQUENCE_BITS=12
• 工作节点ID占5位(WORKER_ID_BITS=5
• 数据中心ID占5位(DATA_CENTER_ID_BITS=5

计算逻辑
工作节点ID需要左移序列号的位数(12位),占据第13~17位。
数据中心ID需要左移序列号+工作节点ID位数(12+5=17位),占据第18~22位。
时间戳需要左移序列号+工作节点ID+数据中心ID位数(12+5+5=22位),占据第23~63位。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


2. 成员变量
private final long dataCenterId;  // 数据中心ID(如:1)
private final long workerId;      // 工作节点ID(如:2)
private long sequence = 0L;       // 序列号(每毫秒从0开始)
private long lastTimestamp = -1L; // 上一次生成ID的时间(毫秒级)

作用
dataCenterIdworkerId:唯一标识一台机器(类似酒店和分店编号)。
sequence:同一毫秒内的递增序号(解决并发问题)。
lastTimestamp:记录上一次生成ID的时间,用于检测时钟回拨。


分步演示生成ID

假设数据

• 当前时间戳:1609459205000(2020-01-01 00:00:05)
• 数据中心ID:1(二进制 00001
• 工作节点ID:2(二进制 00010
• 序列号:3(二进制 000000000011

步骤1:计算时间差
long timestampDiff = currentTimestamp - START_TIMESTAMP;
// 1609459205000 - 1609459200000 = 5000(毫秒)
步骤2:各部分左移

时间戳部分
5000 << 22
二进制:0000000000000000000000000000000000000000010011100010000000000000
数据中心ID部分
1 << 17
二进制:0000000000000000000000000000000000000000000000000010000000000000
工作节点ID部分
2 << 12
二进制:0000000000000000000000000000000000000000000000000000001000000000
序列号部分
3
二进制:0000000000000000000000000000000000000000000000000000000000000011

步骤3:合并各部分(按位或运算)
时间戳部分 | 数据中心ID部分 | 工作节点ID部分 | 序列号部分
= 0000000000000000000000000000000000000000010011100010000000000000| 0000000000000000000000000000000000000000000000000010000000000000| 0000000000000000000000000000000000000000000000000000001000000000| 0000000000000000000000000000000000000000000000000000000000000011
= 0000000000000000000000000000000000000000010011100010001000000011

十进制结果:5000 << 22 | 1 << 17 | 2 << 12 | 3 = 20971520000 + 131072 + 8192 + 3 = 20972852787


关键设计思想

  1. 唯一性:通过dataCenterIdworkerId区分不同机器。
  2. 有序性:时间戳在高位,整体ID趋势递增。
  3. 高性能:位运算和本地计算,无需网络请求。

总结

位移常量:决定每部分在ID中的位置(类似酒店房间号的“区段”)。
成员变量:存储机器标识和时间信息,通过位移拼接成唯一ID。
本质:把时间、机器、序列号信息编码到一个64位数字中,像拼图一样严丝合缝。

http://www.dtcms.com/wzjs/397646.html

相关文章:

  • 崆峒区建设局网站媒体代发网站
  • wordpress 导出 主题西安市seo排名按天优化
  • 做网站找谷谷网络比较好网上推广产品怎么做
  • 临沂网站seo软文广告文案案例
  • 北京网站排名seo百度高级搜索入口
  • 家庭做网站店铺推广软文范例
  • 口腔医院东莞网站建设电脑优化大师下载安装
  • 做旅行网站的意义成都seo
  • 什么建站公司好站长之家网站模板
  • 北京网站制作的公司哪家好google应用商店
  • 搭建网站怎么赚钱网站营销策略有哪些
  • 王也天个人资料优化教程网下载
  • 网站建设相关关键词搜狐酒业峰会
  • 电商网站新闻怎么做的谷歌排名网站优化
  • 东莞软件网站推广淘宝排名查询
  • 高性能网站建设进阶...超级优化空间
  • 有人和兽做的网站seo优化主要工作内容
  • 微科技h5制作网站模板台州关键词优化服务
  • 高端品牌网站设计企业网站建设培训方案怎么做
  • 企业网站的常见服务是什么广告策划案优秀案例
  • 做网站需要多少钱 做百度权重4网站值多少钱
  • 石家庄网站建设找哪家互联网全媒体广告代理
  • 人家做网站是什么成都网站快速开发
  • 较便宜的网站建设昆明长尾词seo怎么优化
  • 网站如何做传输网盘网络营销计划书怎么写
  • 济南智能网站建设哪家好长沙有实力seo优化
  • 长春哪家做网站做的好免费的seo优化
  • 新手学做网站12天婴优化设计六年级下册语文答案
  • 广东网站建设发信息网站出售
  • 专业手机网站开发有广告位怎么找广告商