在项目中,碰到需要按一定规则来生成数据库ID的主键,这样以后数据量达到一定规模是,可以很方便的通过主键id来实现分库分表,查了一些资料,将一些常用ID生成策略的方法及优缺点了解了一下。
1、数据库自增主键
优点:简单;唯一;递增;增幅固定
缺点:写性能决定每秒生成数量上限,扩展差;分布式数据库,主节点挂掉,备节点上时可能有问题(主节点写入成功,日志未同步到备节点,导致id重复)
备注:可有一个写库变成多个库同时写,如1、2、3三个库同时写,初始id分别为1、2、3,自增幅度都为3。这种方式可保证id不重复。但导致id不是绝对递增,而是整体趋势上递增;其次是写入的压力仍然很大,mysql容易成为性能瓶颈。
2、数据库批量生成id
优点:效率高;降低数据库压力
缺点:需考虑安全性问题,防止取到重复id;如果业务需求是每次只生成一个id,性能有问题
备注:利用数据库,初始化一行数据,初始值为1,取10个id,就给该值加10,调用端取返回id值的前10个数值。以上即为批量生成id思路。
3、UUID
优点:本地生成;效率高
缺点:UUID字符串过长,且无实际意义;无法保证递增趋势;建立的索引查询效率低
4、当前时间毫秒与微秒
优点:本地生成;延时低;索引性能高
缺点:1秒内请求过1000后id肯定重复,微秒同理
5、zookeeper生成id
利用zookeeper增加版本号的方式是其中一种。建立节点,每次使节点版本加1。
优点:利用zk集群解决单点问题
缺点:性能不高;id有上限,提供32位id;需要zk服务
参考代码:https://blog.csdn.net/gongzi2311/article/details/58144091
6、snowflake算法
twitter开源分布式生成id算法。
优点:基本解决了所有问题
缺点:每个节点时间可能不同,生成id是整体趋势递增的
参考代码:https://blog.csdn.net/gongzi2311/article/details/58189306
ID的生成
经过整体评估,每秒的并发量、后期可能扩展的服务器数量、数据库数量、供应商增长速度等,最终在snowflake算法的基础上做了一些修改,结构如下:
---------------------------------------------------------
| 1 | 39 | 1 | 7 | 8 | 8 |
---------------------------------------------------------
| A | B | C | D | E | F |
共64位
A:符号位(0);
B:时间差(当前时间与固定时间的差值)
2^39 = 549755813888
每年毫秒数 = 31536000000
使用年限 = 2^39 / 1000 * 60 * 60 *24 *365 = 17年
C:dataCenter(数据中心)
支持2个数据中心
D:workId(服务器)
最多可扩展到128台服务器
E:序列
每毫秒256个序列
F:供应商id
最多支持256个供应商
关于ID生成的具体算法,可以参考snowfla