id基本功能:浅谈ID生成器
id基本功能:浅谈ID生成器第一位为未使用,接下来的41 位为毫秒级时间(41位的长度可以使用 69 年),然后是 5 位 datacenterId和 5 位 workerId (10 位的长度最多支持部署 1024 个节点) ,最后 12 位是毫秒内的计数(12 位的计数顺序号支持每个节点每毫秒产生 4096 个 ID 序号)一共加起来刚好 64 位,为一个 Long 型 (转换成字符串长度为 18) 。示例:323893460451070160,2.每个部门都开发一套 ID 生成器,总体上增加了工作量,增加公司的成本,不利于维护、管理。为什么要开发分布式ID 生成器?原因大体有两点:1.许多业务系统需要对大量的订单、消息进行进行唯一标识,如:金融、电商、支付等。
“叮咚,叮咚……”,微信提示音一声接一声,声音是那么的频繁,有妖气,待俺去看一看。
打开微信,发现我们的技术讨论组里有100 多条未读消息,心想,是不是系统出问题了,怎么消息那么频繁?于是迅速的爬楼,历时 1 秒 23,爬到楼顶,了解事情的来龙去脉,大体意思:下午五点,研发一组在第二会议室开会,会议主题是:开发一个适合多个业务场景的分布式ID 生成器。不一会儿,我们都来到第二会议室,开始了激烈讨论。
可能你们都知道,ID 是某个体系中唯一的编码,用来标识事务,比如:身份标识号、账号、唯一编码、专属号码。
ID生成器又是什么呢?说白了就是生成ID 工具,而在这里我们说的 ID 生成器,却是一个服务(下同)。
为什么要开发分布式ID 生成器?
原因大体有两点:
1.许多业务系统需要对大量的订单、消息进行进行唯一标识,如:金融、电商、支付等。
2.每个部门都开发一套 ID 生成器,总体上增加了工作量,增加公司的成本,不利于维护、管理。
第一位为未使用,接下来的41 位为毫秒级时间(41位的长度可以使用 69 年),然后是 5 位 datacenterId和 5 位 workerId (10 位的长度最多支持部署 1024 个节点) ,最后 12 位是毫秒内的计数(12 位的计数顺序号支持每个节点每毫秒产生 4096 个 ID 序号)一共加起来刚好 64 位,为一个 Long 型 (转换成字符串长度为 18) 。示例:323893460451070160,
323893460455264256。
优点:整体上按照时间自增排序;全局唯一;效率高。
缺点:有序,但不连续;不能同时满足多个系统对ID的需求,不够灵活。
三、 数据库自增序列生成方案
以MySQL 举例,利用给字段设置 auto_increment_increment和 auto_increment_offset 来保证 ID 自增,每次业务使用下列SQL 读写 MySQL 得到 ID 号。
优点:简单,利用现有数据库系统的功能实现;成本小,有 DBA 专业维护。ID 号自增,可以实现一些对 ID 有特殊要求的业务。
缺点:强依赖 DB ,当DB 异常时整个系统不可用,属于致命问题;配置主从复制可以尽可能的增加可用性,但是数据一致性在特殊情况下难以保证;主从切换时的不一致可能会导致重复发号。
ID发号性能瓶颈限制在单台MySQL的读写性能。
四、 基于 ZooKeeper和本地缓存的方案
使用ZooKeeper 作为分段节点协调工具,每台服务器首先从Zookeeper缓存一段,如1-2000的ID,此时Zookeeper 上保存最大值2000,每次获取的时候都会进行判断,如果ID<=2000 ,则更新本地的当前值,如果为2001,则会将Zookeeper 上的最大值更新至 4000,本地缓存段更新为2001-4000,更新的时候使用分布式锁来实现。
优点:全局唯一,效率高。
缺点:维护成本较高,不能同时满足多个系统对ID的需求,不够灵活。
看了许多业内解决方案,有些方案已经基本上可以满足我们的需求,但是不够灵活。我们需要一种灵活、多变、可配置的方案。
经过一番讨论,我们选择了自主研发,核心思想:
使用数据库双 buffer 优化方案,每次从数据库拿取一个号段,当该号段下发50% 时,如果下一个号段未更新,则启动另一个线程去提前更新新号段,当该号段已全部下发完成,且下一个号段准备完成,则切换到下一个号段,就这样一次一次的循环。
举个栗子: 第一次取一个号段100 000 ——110 000 1,当该号段下发到105 000 时,去检查120 000 号段是否更新,如果未更新,启动一个线程去更新号段120 000 ——130 000 2,当1号段已经下发完成,切换到2号段。
这样做的好处是不用频繁的访问数据库,保证了效率,在数据库宕机的一段时间内,服务仍然可生成ID 。
这样就灵活了吗?
NO,这提高性能、效率的方式,要想做到灵活,我们需要设计一张数据库表,表中要区别不同的业务类型,可以设置ID 的前缀规则、后缀规则、长度、步长、最大 ID,保证 ID 灵活、多变、可配置。
数据库表结构设计:
key_name:区分业务
key_length:id长度
key_cache:缓存数量
key_prefix:前缀规则
key_subffix:后缀规则
key_digit:key 生成规则,支持 10 进制、36进制或者 62 进制
数据库表测试数据:
测试服务器配置:Linux 2 核 4G 内存X 2
步长设置为1000,缓冲池设置为 1000,每秒大约可生成16 675 231 次。
分布式 ID 生成器的方案还有很多,各有各的优点,需要你们根据自己的业务场景去选择,“不选贵的,只选对的”。如过觉得这篇文章对你有点用的话,请动一下你发财的小手,帮忙转发一下,感激涕零。