mysql发号系统,[发号器]分布式发号器实现方案,UUID,数据库,snowflake,vesta

概要

分布式 or 微服务架构中,需要产生唯一的编号的服务叫做发号器

需求:

全局唯一(悲观策略使用分布式锁,但是会降低性能)

粗略有序(完全有序更好,但是用锁会导致性能太差)

可反解,便于获取信息差错

可制造,便于数据清洗

高性能

高可用

可伸缩

注意:id不要和token之类的乱序编码混淆,虽然很多场景下他们是一一对应关系,但是id需要可以制造,可以反解,不需要保密性很好,和token的设计初衷是完全相悖

已有方案对比

方案一:UUID

弊端:

没有时间粗略有序

不可反解

不可制造

性能差/长/占用空间

UUID无序,所以数据库存储,导致B+树索引在写的时候过多随机操作

方案二:利用数据库的自增ID

弊端:

数据库移植,扩容,清洗,分库分表都有诸多困难

方案三: twitter开源snowflake

scala语言实现,但是支持和维护较少。

开源项目vesta设计

鉴于前面三个方案都有各自缺陷。本文介绍java的开源项目vesta

设计ID为64位,通过分配不同“位”来组合成一个全局编号

例如(0-63位):

位数

63

62

60-61

30-59

10-29

0-9

含义

版本

类型

生成方式

秒级时间

序列号

机器ID

其中:

版本,类型,生成方式都是配置字段,预留给配置,升级。

秒级时间|序列号|机器ID是 生成的核心逻辑字段。

时间字段预留30位,2^30/(60 * 60 * 24 * 356) = 34,也就是说时间序位34年后消耗完。

*这里注意30位是2进制,如果是10进制,10位就可以是秒级时间戳,而且到 2286/11/21 01:46:40 才会变成11位(10000000000)

补充:时间的2038问题

MySQL默认时间戳(Timestamp)类型的取值范围为

’1970-01-01 00:00:01’ UTC 至’2038-01-19 03:14:07’ UTC,

数据精确到秒级别,

该取值范围包含约22亿个数值,

因此在MySQL内部使用4个字节INT类型来存放时间戳数据:

1、在存储时间戳数据时,

先将本地时区时间转换为UTC时区时间,再将UTC时区时间转换为INT格式的毫秒值(使用UNIX_TIMESTAMP函数),然后存放到数据库中。

2、在读取时间戳数据时,

先将INT格式的毫秒值转换为UTC时区时间(使用FROM_UNIXTIME函数),然后再转换为本地时区时间,最后返回给客户端。

解决方法:

1 数据库存长整型,内存中格式转换

2 如果对于时区没有要求,可以用data代替timefomat

机器ID十位,也就是2^10 = 1024,机器最大支持1024台,完全够用的。

架构设计:

13823bd57b82

image.png

注意事项

1 ID的生成在内存中(不依赖数据库的方案),所以网络IO是系统性能瓶颈,相对于网络io而言,CPU的计算是性能瓶颈,但是CPU计算采用多线程的方式。

2 时间同步

运行发号器的服务,要保证时间的正确性。

ntpdate -u 210.72.145.44

-u:从man ntpdate中可以看出-u参数可以越过防火墙与主机同步;

210.72.145.44:中国国家授时中心的官方服务器。

其他可用中心服务器如下: https://www.cnblogs.com/luchuangao/p/7795293.html

每4年原子时钟和电子时钟会有1秒进行同步,使用ntpdate会调快一秒,1s时间内没有id产生,但是没有影响。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值