1、使用背景

在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识
在美团点评的金融、支付、餐饮、酒店和猫眼电影等产品系统中数据日渐增长,对数据库分库分表后需要唯一ID来标识一条数据或消息;
像订单、优惠券、电影票等都需要有唯一的ID作标识。
此时就需要一个能够生成全局唯一ID的系统是非常有必要的

2、ID生成规则要求

全局唯一

  • 趋势递增
    – 在MySQL的InnoDB引擎中使用的是聚集索引。由于多数RDBMS使用Btree的数据结构来存储索引数据,在主键的选择上面应该尽量使用有序的主键保证写入性能。
  • 单调递增
    – 保证下一个ID大于上一个ID,例如事务版本号、IM增量消息、排序等特殊需求。
  • 信息安全
    – 如果ID是连续的,恶意用户的扒取工作就非常容易做了,直接按顺序访问指定URL即可;如果是订单号就更危险了,竞争对手通过某些订单ID可以直接知道我们一天的单量。所以在一些应用场景下,需要ID无规则不规则。
  • 含时间戳
    – 在开发中快速了解这个分布式id的生成时间。

3、ID号生成系统的可用性要求

高可用
– 发一个获取分布式id的请求,该服务器就要保证99.9999%的情况下给我们创建一个唯一分布式id。
低延迟
– 发一个获取分布式id的请求,服务器回复要快(极速)
高QPS
– 假如并发一口气10万个创建分布式id的请求打过来,服务器要顶得住且能够一下子成功创建10万个分布式id。

4、ID生成的一般通用规则

(1)UUID

  • UUID(Universally Unique Identifier)的标准型式包含32个16进制数字,以连字号分为五段,形式为8-4-4-4-12的36个字符。示例:5f26d8c0-6e09-43cf-9300-6fda1d11985c
  • 优点:性能非常高,本地生成,没有网络消耗;实现了唯一性。
  • 缺点:
    – 无序,无法预测它的生成顺序,不能生成递增有序数字。
    – 主键,ID作为主键时在特定环境中会存在一些问题。例如在做DB主键的场景下,UUID就非常不适用MySQL官方有明确的建议主键要尽量越短越好。
    – 索引,B+树索引的分裂。分布式id作为主键,而主键包含索引,mysql的索引是通过B+树实现的,每一次新的UUID数据的插入,为了查询优化,都会对索引底层的B+树进行修改,又因为UUID是无序的,所以每一次UUID数据的插入会对主键底层的B+树进行很大的修改,这样会导致一些中间节点断裂,也会创造出很多不饱和的节点,这样大大降低了数据库的插入操作。

(2) 数据库自增主键

  • 在分布式里面,数据库的自增ID机制主要原理是:数据库自增ID和mysql数据库的replace into实现的。
  • 这里replace into跟insert功能类似,不同点在于:replace into首先尝试插入数据列表中,如果发现表中已经存在此行数据(根据主键或唯一索引判断)则先删除,再插入;否则则可以直接插入新数据。replace into的含义是插入一条记录,如果表中唯一索引的值遇到冲突,则替换老数据
  • 优点:实现了唯一性、趋势递增。
  • 缺点(集群情况):
    – 系统水平拓展比较困难,比如定义好了步长和机器台数之后,如果需要新添加机器怎么做?假设现在 只有一台机器发号是1,2,3,4,5(步长=1),这时候需要扩容一台新机器:将第二台机器的初值设置的比第一台多很多。当扩容机器达到100台呢?就会出现初值设置会非常大。
    – 数据库压力还是很大,每次获取id都得读写一次数据库,非常影响性能,不符合分布式ID系统低延迟、高QPS的硬性要求。

(3)基于Redis生成全局策略主键

  • 因为Redis是单线程的,天生就能够保证原子性,可以使用原子操作INCR和INCRBY来实现。
  • Redis集群可以获取更高的吞吐量。假如一个集群有台Redis,可以初始化每台Redis的值分别为1,2,3,4,5,然后步长都是5:
    – 各个Redis生成的ID为:
    A:1,6,11,16,21
    B:2,7,12,17,22
    C:3,8,13,18,23
    D:4,9,14,19,24
    E:5,10,15,20,25
  • 缺点:需要额外配置和维护Redis集群等工作才能获得id,比较麻烦。

5、雪花算法

Twitter的分布式自增ID算法snowflake

  • ID按照时间有序生成。
  • 是一个64bit大小的整数,为一个Long型(转化为字符串长度最多为19位)。
  • 分布式系统内不会产生ID碰撞(由datacenter和workId作区分),效率高。

雪花算法的几个核心组成部分:

  • 1bit 符号位:不用,因为二进制中最高位是符号位(1表示负数,0表示正数)。生成的id一般都是用正数,所以最高位固定位0。
  • 41bit时间戳位:可以表示2^41 - 1个毫秒值。
  • 可以部署2^10=1024个节点,10bit工作进程位=5位datacenterId+5位workerId。
  • 12bit序列号位:用来记录同毫秒内产生的不同的id。同一机器同一时间戳(毫秒)内可以产生2^12=4095个ID序号。

主键生成策略之雪花算法相关推荐

  1. 雪花算法及分布式主键生成策略详解

    目前雪花算法常应用于分布式环境下作为分布式主键的首选,本文详细介绍下雪花算法及相关分布式主键的生成策略. 如下内容已本文PPT讲解内容为基础. 本次内容共包括4部分:分布式主键生成策略,雪花算法详解, ...

  2. MyBatisPlus主键生成策略

    简介 我们可以通过 @TableId 注解的 type 属性来设置主键 id 的增长策略,一共有如下几种主键策略,可根据情况自由配置. AUTO(数据库 ID 自增) 对于像 MySQL 这样的支持主 ...

  3. [MyBatisPlus]常用注解_@TableName_@TableId_@TableField_@TableLogic通过全局配置配置主键生成策略

    常用注解 @TableName 设置实体类所对应的表名 如果全部表都有某个前缀,难道我们要通过一个一个加注解的方式来解决实体类对应表名问题吗? 我们可以通过配置文件来解决这个问题: @TableId ...

  4. Mybatis-Plus主键生成策略详解

    文章目录 前言 一.官网 二.主键注解@TableId说明 1.源码 2.作用 3.使用 三.主键生成策略-IdType枚举说明 1.源码 2.说明 3.全局设置 三.ID生成器介绍 1.Identi ...

  5. hibernate 7大主键生成策略详解与对象状态

    一:代理主键_主键自增 1.identity 1.采用底层数据库本身提供的主键生成标识符,条件是数据库支持自动增长数据类型 2.该生成器要求在数据库中把主键定义成为自增长类型.适用于代理主键 2.in ...

  6. Hibernate各种主键生成策略与配置详解 - 真的很详细啊!!

    1.assigned 主键由外部程序负责生成,在 save() 之前必须指定一个.Hibernate不负责维护主键生成.与Hibernate和底层数据库都无关,可以跨数据库.在存储对象前,必须要使用主 ...

  7. hibernate之主键生成策略

    一.主键类型 1.自然主键(主键本身就是表中的一个字段,实体中一个具体的属性) 表中已经具有某字段,并且该字段具有业务含义作为主键,称之为自然主键. 例如:在person表中的身份证号,既是唯一的,又 ...

  8. 基于按annotation的hibernate主键生成策略

    这里讨论代理主键,业务主键(比如说复合键等)这里不讨论. 一.JPA通用策略生成器 通过annotation来映射hibernate实体的,基于annotation的hibernate主键标识为@Id ...

  9. Hibernate标识符属性(主键)生成策略全析

    数据库中的主键能够唯一识别一条记录,它可以是一个字段也可以是多个字段的组合.主键的主要作用是标识表中的一条记录,还有和其他表中的数据进行关联.数据库中的主键类型必须符合唯一性约束和非空约束.作为附加属 ...

最新文章

  1. notification antd 弹窗使用示例
  2. 猜数字游戏,正确率为零
  3. mysql标准化存储结构_Atitit.自定义存储引擎的接口设计 api 标准化 attilax 总结  mysql...
  4. pitr 原理_PostgreSQL基于时间点恢复(PITR)
  5. 【OpenCV】OpenCV函数精讲之 -- 颜色空间缩减及LUT函数
  6. matlab 调整灰度,matlab灰度图像调整及imadjust函数的用法详解
  7. Android 系统(48)---WindowManager.LayoutParams 详解
  8. 用 3 只“鸽子”,告诉你闪电网络如何改变加密消息传递方式!
  9. 如何加入微服务 Apache ServiceComb 社区
  10. asppython份额_为什么JAVA份额那么高,存在感却不如Python?
  11. HTTPSConnectionPool(host=‘api.github.com‘, port=443): Max retries exceeded with url
  12. java为什么序列化_什么是Java序列化、为什么要序列化、JAVA序列化有哪些方式(性能由低至高)...
  13. 如何使用SPSS进行判别分析
  14. 虚拟光驱 安装深度linux,今天试装了深度精简系统Deepin-LiteXP-SP3 6.2 小盘
  15. 服务器优盘启动安装win7系统教程,u盘装win7系统详细教程图解
  16. JavaScript - 动画介绍与学习
  17. 瑞士轮赛制模拟器_【入门必读】VGC综合介绍(下篇)【翻译】
  18. APP设计之启动页和广告页
  19. springboot 启动banner 打印 佛祖保佑
  20. 微信小程序——关于时间

热门文章

  1. 图片翻转代码linux,Android实现图片顺时逆时旋转及拖拽显示效果
  2. Flutter 返回按钮的监听
  3. 【ASP.NET MVC4】第六课:在MVC 中使用 HTML 辅助方法输出表单
  4. 通过Postman实现压力测试
  5. c语言入门自学ppt文库,《C语言入门基础》PPT课件.ppt
  6. 如何申请创建数据分析项目组合
  7. 获取layui表格单元格的数据_Layui数据表格之获取表格中所有的数据方法
  8. 机械革命x6ti拆机教程
  9. Ubuntu配置中文输入法
  10. 从0到1,云服务助力全民直播快速构建大数据平台