惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Security Archives - TechRepublic
MongoDB | Blog
MongoDB | Blog
量子位
博客园 - 叶小钗
罗磊的独立博客
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Hacker News: Ask HN
Hacker News: Ask HN
MyScale Blog
MyScale Blog
GbyAI
GbyAI
Help Net Security
Help Net Security
Y
Y Combinator Blog
Engineering at Meta
Engineering at Meta
Hacker News - Newest:
Hacker News - Newest: "LLM"
Latest news
Latest news
H
Hacker News: Front Page
Blog — PlanetScale
Blog — PlanetScale
雷峰网
雷峰网
Microsoft Azure Blog
Microsoft Azure Blog
P
Proofpoint News Feed
C
CXSECURITY Database RSS Feed - CXSecurity.com
Scott Helme
Scott Helme
S
Schneier on Security
博客园 - 司徒正美
Hugging Face - Blog
Hugging Face - Blog
S
Security @ Cisco Blogs
Recorded Future
Recorded Future
S
Securelist
博客园 - Franky
Application and Cybersecurity Blog
Application and Cybersecurity Blog
A
About on SuperTechFans
N
News and Events Feed by Topic
AI
AI
T
Tenable Blog
N
News | PayPal Newsroom
C
Cybersecurity and Infrastructure Security Agency CISA
V
V2EX - 技术
T
Threat Research - Cisco Blogs
Cisco Talos Blog
Cisco Talos Blog
L
LINUX DO - 热门话题
N
Netflix TechBlog - Medium
S
SegmentFault 最新的问题
T
The Blog of Author Tim Ferriss
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Google Online Security Blog
Google Online Security Blog
S
Security Affairs
Webroot Blog
Webroot Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
博客园 - 三生石上(FineUI控件)
C
Comments on: Blog
G
GRAHAM CLULEY

博客园 - 网鱼

雪花算法:生成分布式全局唯一ID 数据加密共享与签名方案 Java 8中处理集合的优雅姿势——Stream 消息中间件选型分析——从Kafka与RabbitMQ的对比来看全局 从概念到底层技术,一文看懂区块链架构设计(附知识图谱) 以太坊源码分析——BlockChain 超级账本实践——基于docker从零搭建联盟链 Hyperledger Fabric V1.0– 开发者快速入门 超级账本Fabric教程(一):超级账本入门 区块链技术基础语言(三十二):Go语言网络编程(下) 区块链技术基础语言(三十一):Go语言网络编程(上) 区块链技术基础语言(三十):Go语言常用工具包(下) 区块链技术语言(二十九)—Go语言常用工具包(上) 区块链技术语言(二十八)——Go语言并发编程(下) 区块链技术语言(二十七)——Go语言并发编程(上) 区块链技术语言(二十六)——Go语言异常处理 - 网鱼 区块链技术语言(二十五)——面向对象:接口 - 网鱼 区块链技术语言(二十四)——Go语言面向对象:匿名组合 区块链技术语言(二十三)——Go语言面向对象:方法
Twitter的分布式自增ID雪花算法snowflake (Java版)
网鱼 · 2019-03-22 · via 博客园 - 网鱼

概述

分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。

有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。

twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移到Cassandra,因为Cassandra没有顺序ID生成机制,所以开发了这样一套全局唯一ID生成服务。

结构

snowflake的结构如下(每部分用-分开):

0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000

第一位为未使用,接下来的41位为毫秒级时间(41位的长度可以使用69年),然后是5位datacenterId和5位workerId(10位的长度最多支持部署1024个节点) ,最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)

一共加起来刚好64位,为一个Long型。(转换成字符串长度为18)

snowflake生成的ID整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和workerId作区分),并且效率较高。据说:snowflake每秒能够产生26万个ID。

  1. private final long twepoch = 1288834974657L;

  2. private final long workerIdBits = 5L;

  3. private final long datacenterIdBits = 5L;

  4. private final long maxWorkerId = -1L ^ (-1L << workerIdBits);

  5. private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);

  6. private final long sequenceBits = 12L;

  7. private final long workerIdShift = sequenceBits;

  8. private final long datacenterIdShift = sequenceBits + workerIdBits;

  9. private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

  10. private final long sequenceMask = -1L ^ (-1L << sequenceBits);

  11. private long datacenterId;

  12. private long sequence = 0L;

  13. private long lastTimestamp = -1L;

  14. public IdWorker(long workerId, long datacenterId) {

  15. if (workerId > maxWorkerId || workerId < 0) {

  16. throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));

  17. if (datacenterId > maxDatacenterId || datacenterId < 0) {

  18. throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));

  19. this.workerId = workerId;

  20. this.datacenterId = datacenterId;

  21. public synchronized long nextId() {

  22. long timestamp = timeGen();

  23. if (timestamp < lastTimestamp) {

  24. throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));

  25. if (lastTimestamp == timestamp) {

  26. sequence = (sequence + 1) & sequenceMask;

  27. timestamp = tilNextMillis(lastTimestamp);

  28. lastTimestamp = timestamp;

  29. return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;

  30. protected long tilNextMillis(long lastTimestamp) {

  31. long timestamp = timeGen();

  32. while (timestamp <= lastTimestamp) {

  33. protected long timeGen() {

  34. return System.currentTimeMillis();

  35. public static void main(String[] args) {

  36. IdWorker idWorker = new IdWorker(0, 0);

  37. for (int i = 0; i < 1000; i++) {

  38. long id = idWorker.nextId();

posted @ 2019-03-22 14:19  网鱼  阅读(945)  评论()    收藏  举报