那些惊艳的算法们(四)——唯一ID生成器snowflake

那些惊艳的算法们(四)——唯一ID生成器snowflake同步发表在个人博客中:http://blog.lanjingdejia.com/articles/2019/01/15/1547516544183.html分布式全局唯一ID生成器很多场景需要使用全局唯一ID,用来标识唯一一条消息,唯一一笔交易,唯一一个用户,唯一一张图片等等。传统数据库表的自增主键是很简单的一种实现方式,前提是你没有分库,也没有分表,如果你分表了,id就会重复,失去唯一性…

大家好,又见面了,我是你们的朋友全栈君。

分布式全局唯一ID生成器

很多场景需要使用全局唯一ID,用来标识唯一一条消息,唯一一笔交易,唯一一个用户,唯一一张图片等等。
传统数据库表的自增主键是很简单的一种实现方式,前提是你没有分库,也没有分表,如果你分表了,id就会重复,失去唯一性:
imagepng

当然,通过数据库的一些配置,使不同的分表以不同的起始值但是相同的步长自增,可以绕开这个限制:

imagepng

但是,如果哪天发现数据量增大,原先的分表不够用了,需要扩容,这时,就很麻烦很难搞了。
所以,如果存在一种和业务数据无关的全局唯一ID生成器就好了。开动脑筋,我们能想到的有以下几种:

时间戳

用时间做唯一id,这个在并发比较高或者分布式环境中基本不可行,统一时间生成的id是重复的,不满足全局唯一。

利用数据库自增

依然利用数据库产生自增id,保证唯一性,和开头提到的不同之处是,单独使用一张(或固定几张)数据库表专门用来产生自增id,与业务无关,后续不再重新分表,数据量大时,可以删除早一些时候产生的数据。
这样做的好处是,实现简单,容易理解。
不好的地方是,严重依赖数据库,id产生速率受数据库性能以及连接数据库的网络影响。

利用Redis原子操作incrBy

好处:实现简单,容易理解。
坏处:依赖Redis,且Redis需要持久化。

UUID/GUID

好处:使用非常简单,不需要依赖其他设施。
坏处:太长,128bit,不适合做数据库主键。

snowflake

通常情况下,用时间来表示是最简单的,如果同一时间(毫秒)有很多请求进来怎么办?
时间戳后面拼接上一个数字,这个数字可以通过锁控制每次递增,每毫秒清零,重新开始递增。

即便这样,只是解决了单机的问题,如果是分布式环境,不同的机器,还是可能产生一样的id的,这怎么解决?
在上述时间戳和数字的基础上在拼接上机器的id,这样就不会重复了。

不同的数据中心,机器id是可能重复的,怎么搞?
再拼接上数据中心的id就行了。

不同的星球上。。。

思想朴实无华,但是大道至简。

最终产生的id是这个样子的,时间戳,工作机器id,序列号可以根据实际需要调整长度(通常情况下不需要调整,完全够用),总体64bit就行:
imagepng

snowflake名字起得真好

雪花(snowflake)的形状和算法的思想十分吻合,沿着主干(时间戳),如果有重复,那么分叉分出机器id,如果仍有重复,再分叉,分出序列号
imagepng

好处与不足

snowflake有以下几个特点:

算法简单,不需要依靠额外组件

id可以直接靠算法在内存中产生,靠锁控制并发,不需有诸如MySQL,Redis这样的外部依赖,无维护成本。

长度合适

snowflake产生的id长度为64bit,对应大多数语言的long类型,用于作为数据库唯一键建立索引时,也不会因为长度过大影响性能。

趋势递增

snowflake产生的id并不是严格递增的,而是趋势递增的。
这是因为,当id生成器分布式部署的时候,比如统一毫秒由不同机器产生的id,时间戳的部分肯定是一样的,后面机器id的部分并不一定是递增的。
举个例子,有两个机器,id分别是0和1,那么同一毫秒内产生的id可能是这样的顺序:
imagepng

从图中可以看出,由于机器id的存在,在同1毫秒内产生的id并不一定是递增的,但是因为时间戳的存在,在毫秒间总体上id是递增的。
所以总体上说snowflake产生的id是趋势递增的。

为何追求递增

为何追求递增?因为递增最大的优势就是对磁盘IO是友好的。
熟悉磁盘结构的同学们都知道,随机写的效率是很慢的,因为磁头需要转动到指定的位置,这个磁头转动的过程比起cpu或者内存来,完全不是一个数量级的,太慢太慢了,所以如果能尽可能的使数据靠近在一一起(递增就能靠在一起),那么就不需要频繁的抬起磁头,转动磁盘,写数据了,一路写到底会快很多。
一些大型分布式数据库,比如HBase,ElasticSearch等,也都是利用顺序写这个特点提高数据的写入性能的。

隐患

snowflake并不完美,因为有一种情况,snowflake产生的id是有可能会出现重复的。
为什么会重复,我们再回头看看snowflake产生的id的组成:时间戳+机器id+序列号。
这三部分,机器id可以不重复,序列号也可以做到不重复,那唯一可能重复的就是时间戳了。
什么?时间怎么回重复?时间明明是一直向前的,除非时间倒退,退回到之前的某个时间点,再次产生的id才可能是重复的。
你说对了,人类感受的时间是不会倒退的,但是,机器上的时间都是时钟,时钟可能会因为种种原因变慢了或者变快了,比如有一天你(或者机器上的时间同步器)发现有一台机器的时钟变快了,于是往回拨1秒,然后。。。 你懂的

时钟的问题,一直都是老大难,某些对时间及其敏感的程序,甚至会考虑使用GPS上的原子钟来做时钟同步,或者,干脆有土豪(某歌)直接在数据中心自己搞原子钟,然并卵,时间同步时的网络传输延迟、抖动,依然无解。
永远都是只能减小,无法消灭。

##最后
忍不住再夸一下算法的名字,snowflake,真是美妙。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/151073.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • python 查tensorflow版本_如何查看tensorflow的版本「建议收藏」

    python 查tensorflow版本_如何查看tensorflow的版本「建议收藏」本文介绍如何使用pip查看tensorflow的版本号,请查看如下步骤。本文使用的windows10系统,如为linux系统也是同样用pip命令查看。工具/原料window10python3.7(其他python也可以)方法/步骤1通过快捷键windows键+R,打开运行框,输入“cmd”命令,打开命令行窗口2在命令行窗口中输入命令piplist3命令执行后,会列出当前python环…

    2022年6月25日
    301
  • 求矩阵的逆的三种方法

    求矩阵的逆的三种方法我们知道求矩阵的逆具有非常重要的意义,本文分享给大家如何针对3阶以内的方阵,求出逆矩阵的3种手算方法:待定系数法、伴随矩阵法、初等变换法(只介绍初等行变换)待定系数法求逆矩阵 1 首先,我们来看如何使用待定系数法,求矩阵的逆。 举例: 矩阵A= 12 -1-3 2 假设所求的逆矩阵为 ab cd 则 3 从而可以得出方程组 a+2c=1 b+2d=0 -a-3c=0 -b-3d=1

    2022年8月21日
    3
  • java学习——java中的反射学习笔记「建议收藏」

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

    2022年2月26日
    38
  • 关于insertBefore是怎么使用的

    关于insertBefore是怎么使用的insertBefore接收两个参数第一个参数是将要进行插前操作的对象第二个参数是被插前的对象也可以称为参考对象调用者为你要操作的元素的父级如下例:<!DOCTYPE ht

    2022年7月2日
    20
  • ethtool用法 linux_ethtool用法

    ethtool用法 linux_ethtool用法Linux/Unix命令之Ethtool描述:Ethtool是用于查询及设置网卡参数的命令。概要:ethtoolethX//查询ethX网口基本设置ethtool–h//显示ethtool的命令帮助(help)ethtool–iethX//查询ethX网口的相关信息ethtool–dethX//查询ethX网口注册性信息ethtool–rethX//重置ethX网口到自适应模式ethtoo…

    2025年6月9日
    0
  • 图文并茂 RAID 技术全解 – RAID0、RAID1、RAID5、RAID10

    图文并茂 RAID 技术全解 – RAID0、RAID1、RAID5、RAID10    RAID技术相信大家都有接触过,尤其是服务器运维人员,RAID概念很多,有时候会概念混淆。这篇文章为网络转载,写得相当不错,它对RAID技术的概念特征、基本原理、关键技术、各种等级和发展现状进行了全面的阐述,并为用户如何进行应用选择提供了基本原则,对于初学者应该有很大的帮助。一、RAID概述  1988年美国加州大学伯克利分校的D.A.Patterson教授等首次…

    2022年7月15日
    24

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号