mysql分布式id方案

前言:
id是数据唯一标识带索引可以快速查找到数据,在mysql中大家一般用uuid或者自增主键来做唯一标识,uuid因为无序并且过长所以不适合做唯一标识,而自增主键因为数据库分库分表自增很容易出现id冲突,所以需要一个单独的逻辑或机制来生成唯一ID,这就叫做分布式id和全局id

数据库多主模式

将数据库设定成多主模式这样每次新增数据都会去做同步这样避免生成一样的id
缺点:这样会有写扩大的问题对性能有影响

号段模式

滴滴Tinyid

这种相当于每个数据库有一个号段,假设ABC三个数据库,一个数据库一次可以申请1000个id,当快使用完之后再去异步申请一个号段
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pgSyy3Wk-1605837443017)(en-resource://database/714:0)]

关于号段算法实现,tinyid参考了美团leaf,并对其做了扩展,增加了多db支持和tinyid-client,从而获得了更好的性能和可用性。

升级版本号段模式

假设三台ABC,起始自增为012,然后自增变量为数据库服务的count,这样就是第一次自增3:4:5第二次自增6:7:8
这样可以在不引入其他框架运用逻辑来完成
缺点:需要规定数据库个数,并且预留以后可能增加的节点个数例如当前只有三台,可能增加为10台那么自增变量就需要为10

雪花算法

snowflake是twitter开源的分布式ID生成算法,是一种算法,所以它和上面的三种生成分布式ID机制不太一样,它不依赖数据库。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YNTzYXti-1605837443021)(en-resource://database/716:0)]

  • 第一个bit位是标识部分,在java中由于long的最高位是符号位,正数是0,负数是1,一般生成的ID为正数,所以固定为0。
  • 时间戳部分占41bit,这个是毫秒级的时间,一般实现上不会存储当前的时间戳,而是时间戳的差值(当前时间-固定的开始时间),这样可以使产生的ID从更小值开始;41位的时间戳可以使用69年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年
  • 工作机器id占10bit,这里比较灵活,比如,可以使用前5位作为数据中心机房标识,后5位作为单机房机器标识,可以部署1024个节点。
  • 序列号部分占12bit,支持同一毫秒内同一个节点可以生成4096个ID

snowflake算法实现起来并不难,提供一个github上用java实现的:https://github.com/beyondfengyu/SnowFlake在大厂里,其实并没有直接使用snowflake,而是进行了改造,因为snowflake算法中最难实践的就是工作机器id,原始的snowflake算法需要人工去为每台机器去指定一个机器id,并配置在某个地方从而让snowflake从此处获取机器id。但是在大厂里,机器是很多的,人力成本太大且容易出错,所以大厂对snowflake进行了改造。

百度(uid-generator)

https://github.com/baidu/uid-generator

美团(Leaf)

支持号段模式,也支持snowflake模式。
https://github.com/Meituan-Dianping/Leaf

参考文档

https://github.com/didi/tinyid/wiki/tinyid%E5%8E%9F%E7%90%86%E4%BB%8B%E7%BB%8D

猜你喜欢

转载自blog.csdn.net/zhaohan___/article/details/109840034