1. SnowFlake 算法介绍

雪花算法是由 Twitter 公司开源的可在分布式系统中产生一个全局唯一 ID 的算法。最初 Twitter 把存储系统从 MySQL 迁移到 Cassandra,因为 Cassandra 没有顺序ID生成机制,所以开发了这样一套全局唯一ID生成服务。

SnowFlake 算法生成的 ID 是一个 64 位的整数,它的结构如下图所示:


  • 第一部分:1bit 符号位,由于都是生成 ID 都是正数,所以第一位统一为0;

  • 第二部分:41 bit 时间戳,单位是毫秒,41 位可以表示的数字多达 2^41 - 1,换算成年就是 69 年;

  • 第三部分:5 bit 机房 ID,代表最多支持 32 个机房;

  • 第四部分:5 bit 机器 ID,代表每个机房最多支持 32 台机器;

  • 第五部分:12 bit,记录同一时间(毫秒)内产生的不同 id,也就是说同一毫秒内可以产生4096个不同 id。

SnowFlake 生成的 ID 整体上按照时间自增排序,并且整个分布式系统不会产生 ID 碰撞(由 DataCenterID 和 WorkerID 区分),并且效率较高。

2. 实现

在实现 SnowFlake 基本功能的基础上,增加部分拓展功能:

  • 定义开始时间戳,默认为 2020/01/01 08:00:00,如果使用默认的时间戳位数,那么该程序生成 ID 大概可以使用到 2089 年;

  • 机房 ID 、机器 ID 和 序列 ID 三个数据段长度可以自定义,通过构造函数传入。

2.1 方法介绍

  • timeGen

    • 描述:生成当前毫秒时间戳,相对于 2020年1月1日 8:00:00

    • 属性:private

    • 返回值:当前毫秒时间戳

  • tilNextMillis

    • 描述:阻塞直到下一毫秒

    • 属性:private

    • 返回值:下一毫秒时间戳

  • nextId

    • 描述:生成一个新的 ID

    • 返回值:新 ID

2.2流程图


2.3 代码实现

 1// SnowFlake.h 2 3#pragma once 4 5#include  6#include  7#include  8 9extern const uint64_t INVALID_ID = 0;1011class SnowFlake12{13public:14    SnowFlake(uint64_t datacenterId, uint64_t machineId, 15        uint64_t datacenterIdBit = 5, uint64_t machineIdBit = 5, uint64_t sequenceBit = 12)16        :   datacenterIdBit_(datacenterIdBit),17            machineIdBit_(machineIdBit),18            sequenceBit_(sequenceBit),19            maxDataCenterCount_(-1 ^ (uint64_t(-1) <20            maxMachineCount_(-1 ^ (uint64_t(-1) <21            maxSequenceCount_(-1 ^ (uint64_t(-1) <22            machineShift_(sequenceBit_),23            dataCenterShift_(machineShift_ + machineIdBit_),24            timestampShift_(dataCenterShift_ + datacenterIdBit_),25            datacenterId_(datacenterId),26            machineId_(machineId)            27    {28        if (datacenterIdBit + machineIdBit + sequenceBit != 64 - 1 - 41)29        {30            std::cout <"datacenterIdBit + machineIdBit + sequenceBit != 22, please check." <std::endl;31            exit(0);32        }33    }34    ~SnowFlake() {}3536    uint64_t nextId() {37        std::unique_lock<std::mutex> lock(mutex_);38        uint64_t currTimestsmp = timeGen();39        if (currTimestsmp 40            std::cout <"Clock has been moved backwards. Generate id failed." <std::endl;41            return INVALID_ID;42        }4344        if (currTimestsmp == lastTimestamp_) {45            sequence_ = (sequence_ + 1) & maxSequenceCount_;46            if (0 == sequence_) {47                currTimestsmp = tilNextMillis();48            }49        }50        else {51            sequence_ = 0;52        }5354        lastTimestamp_ = currTimestsmp;55        return lastTimestamp_ <56            | datacenterId_ <57            | machineShift_ <58            | sequence_;59    }6061protected:62    uint64_t timeGen() const {63        return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() - startTimestamp_;64    }6566    uint64_t tilNextMillis() const {67        uint64_t mill = timeGen();68        while (mill <= lastTimestamp_) {69            mill = timeGen();70        }71        return mill;72    }7374private:75    const uint64_t startTimestamp_ = 1577836800000;    // 2020/01/01 08:00:0076    const uint64_t datacenterIdBit_;    77    const uint64_t machineIdBit_;78    const uint64_t sequenceBit_;7980    const uint64_t maxMachineCount_;81    const uint64_t maxDataCenterCount_;82    const uint64_t maxSequenceCount_;8384    const uint64_t machineShift_;85    const uint64_t dataCenterShift_;86    const uint64_t timestampShift_;8788    uint64_t lastTimestamp_ = 0;89    uint64_t datacenterId_  = 0;90    uint64_t machineId_     = 0;91    uint64_t sequence_      = 0;9293    std::mutex mutex_;94};

2.4 测试程序

该测试程序测试每秒生成 ID 的数量,基本上每秒可以生成 900000~1100000 左右:

 1#include  2 3#include "SnowFlake.h" 4 5int main() 6{ 7    std::chrono::steady_clock::time_point start_; 8    std::chrono::steady_clock::time_point end_; 910    SnowFlake uuid(5 , 10);11    start_ = std::chrono::steady_clock::now();12    uint64_t cnt = 0;1314    while (std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - start_).count() 1000)15    {16        cnt++;17        uuid.nextId();18    }1920    std::cout <"SnowFlake generates " <" ids one second." <std::endl;21}

系列文章回顾

┣ MySQL从零开始:数据库简介

┣ MySQL 从零开始:02 MySQL安装

┣ MySQL 从零开始:03 基本入门语句

┣ MySQL 从零开始:04 表的增删改查

┣ MySQL 从零开始:05 MySQL数据类型

┣ MySQL 从零开始:06 数据检索

┣ MySQL 从零开始:07 数据搜索

┣ MySQL 从零开始:08 番外:随机生成数据库数据

┣ MySQL 从零开始:09 计算字段

改进型 clock 页面置换算法实现_ID生成算法雪花算法介绍及实现相关推荐

  1. SpringBoot实战:设备唯一ID生成【雪花算法、分布式应用】

    目录 SpringBoot实战:设备唯一ID生成[雪花算法.分布式应用] 背景: snowflake(雪花算法)方案: 实现: 雪花算法生成ID: 二维码打包: 多线程优化-批量插入: 二维码识别+扫 ...

  2. [分布式] ------ 全局唯一id生成之雪花算法(Twitter_Snowflake)

    雪花算法(Twitter_Snowflake) 我们知道,分布式全局唯一id的生成,一般是以下几种: 基于雪花算法生成 基于数据库 基于redis 基于zookeeper 本文说下雪花算法,后面附源码 ...

  3. 全局唯一id生成之雪花算法

    雪花算法(Twitter_Snowflake) 我们知道,分布式全局唯一id的生成,一般是以下几种: 基于雪花算法生成 基于数据库 基于redis 基于zookeeper 本文说下雪花算法,后面附源码 ...

  4. Java 分布式生成ID—雪花算法

    一.概述 1.SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图: 1位,不用.二进制中最高位为1的都是负数,但是我们生成的id一般都使用整数,所以这个最高位固定是0 ● ...

  5. 时钟页面置换算法c语言,clock置换算法例题(改进clock置换算法例题讲解)

    Clock页面置换算法: 6)动态给出页面调用序列并进行调度: 7)输出置换结. C++编程要? 考试用 哪位大侠 帮帮 快点 谢谢了 这很简单啊,要打字太多了.不过网上这类算法举例很少,就看你怎么理 ...

  6. 计算机操作系统——页面置换算法

    声明:本篇博客参考书籍<计算机操作系统>(西安电子科技大学出版社) 文章目录 一.最佳页面置换算法 1.基本知识 2.算法思想 二.先进先出(FIFO)页面置换算法 1.基本知识 2.算法 ...

  7. 操作系统:基于页面置换算法的缓存原理详解(下)

    概述: 在上一篇<操作系统:基于页面置换算法的缓存原理详解(上)>中,我们主要阐述了FIFO.LRU和Clock页面置换算法.接着上一篇说到的,本文也有三个核心算法要讲解.分别是LFU(L ...

  8. 操作系统:基于页面置换算法的缓存原理详解(上)

    概述: 作为一个学计算机的一定听过缓存(注意这里是缓存,不是缓冲).比如我们在登录网页时,网页就可以缓存一些用户信息:比如我们在写界面代码的时候,可能就会遇到界面的绘制是基于一些缓存算法的.所以,了解 ...

  9. lru页面置换算法_C|内存管理|从LRU王国到NRU王国

    缓存机制中,当发生页冲突时,操作系统将会调用页面置换算法进行淘汰,而我们这篇文章中重点介绍随机访问情况下效率较高的两种算法. LRU:Least Recently Used NRU:Not Recen ...

最新文章

  1. 转载:薪资谈判应该避免的7个错误
  2. Kubernetes网络一年发展动态与未来趋势
  3. OpenLayers加载搜狗地图
  4. Leetcode PHP题解--D5 804. Unique Morse Code Words
  5. 获取2个地址之间的距离(高德API)
  6. 输出空格隔开换行_【前端干货】CSS 的空格处理
  7. leetcode127. 单词接龙(bfs)
  8. zabbix agent 类型所有key
  9. 5个月内要完成的东西
  10. linux mem cache,Linux内存:MemTotal、MemFree、MemAvailable三者区别
  11. 《坦克世界》1.0+:使用 CPU 优化的图形和物理丰富用户体验
  12. c语言中int型变量的字节数
  13. 物联网卡封卡原因有哪些
  14. Kali Linux萌新特别篇
  15. 宁波市建筑物矢量数据(Shp格式+带高度)
  16. 模糊评价模型-以2018美赛为例
  17. 我在2016年读到的
  18. 【Lua杂谈】debug.getinfo源码分析——使用C API重写lfunctimer
  19. 电力系统远动及其规约
  20. 大话设计模式:第27章 解释器模式

热门文章

  1. CVPR 2020 | 用机器学习打造计数君,谷歌RepNet可自动计数视频重复片段
  2. 浅谈lambda表达式最通俗易懂的讲解
  3. 【每日一算法】二叉搜索树结点最小距离
  4. TCP网络应用程序的注意点
  5. 爬虫之requests模块cookieJar对象转换为cookies字典的方法
  6. 小甲鱼关于push,pop指令的一个编程题
  7. 绝对不容错过:最完整的检测模型评估指标mAP计算指南(附代码)在这里!
  8. 笔记 | 深入理解深度学习语义分割
  9. 【OpenCV 4开发详解】Canny算法
  10. 第五篇:协调和协定之选举算法