唯一ID可以标识数据的唯一性,在分布式系统中生成唯一ID的方案有很多,常见的方式大概有以下三种:
依赖数据库,使用如MySQL自增列或Oracle序列等。
根据UUID生成
snowflake雪花算法
为什么使用snowflake生成ID
使用uuid生成订单号这类东西也能凑合用,但是它有着罄竹难书的“罪行”:肉眼可见,它是无序的;长度是64位数字字母随机组合的字符串,占用空间巨大;完全不具备业务属性,也就是说使用uuid你完全无法推算出它到底是干嘛的;因为无序,所以趋势递增就更不用指望了;所以用uuid生成订单号就是自杀行为,适合它的是类似生成token令牌的场景。
雪花算法(snowflake)是Twitter开源的分布式ID生成算法,结果是一个long型的ID。为了满足Twitter每秒上万条消息的请求,每条消息都必须分配一条唯一的id,这些id还需要一些大致的顺序,让twitter可以通过一定的索引来进行检索,而在Twitter庞大的分布式系统中不同机器产生的id必须又必须不同。它的好处显而易见,不仅全局唯一,并且有序按时间递增,同时占用空间少,生成的id仅仅是19位的整形数字,正好契合mysql的bigint数据类型,简直完美。
核心思想
其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号,最后还有一个符号位,永远是0。
组成:
优势
整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。 毫秒数在高位,自增序列在低位,整个ID都是趋势递增的。 不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的。 可以根据自身业务特性分配bit位,非常灵活。
缺陷
强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。
安装库
1 | pip install pysnowflake |
开启服务
1 | snowflake_start_server --work=1 |
1 | 指定端口开启服务 |
服务信息
1 | import snowflake.client |
获取ID
1 | import snowflake.client |
根据ID反解析服务
1 | import snowflake.client |
使用bigint存储
在使用好处显而易见,不仅全局唯一,并且有序按时间递增,同时占用空间少,生成的id仅仅是19位的整形数字,正好契合mysql的bigint数据类型,简直完美。
但是使用bigint有个bug,就是19位数字传到前端会发生关于js数字精度丢失问题。
关于精度丢失问题