首页 > 图灵资讯 > java面试题>正文

金三银四精选面试题-分库分表之后,id 主键如何处理?

2023-11-20 09:29:27

 

分库分表之后,id 主键如何处理?

其实这是分库分表之后你必然要面对的一个问题,就是 id 咋生成?因为要是分成多个表之后,每个表都是从 1 开始累加,那肯定不对啊,需要一个全局唯一的 id 来支持。所以这都是你实际生产环境中必须考虑的问题。

数据库自增长ID

这个就是说你的系统里每次得到一个 id,都是往一个库的一个表里插入一条没什么业务含义的数据,然后获取一个数据库自增的一个 id。拿到这个 id 之后再往对应的分库分表里去写入。

优点:非常简单,有序递增,方便分页和排序。

缺点:分库分表后,同一数据表的自增ID容易重复,无法直接使用(可以设置步长,但局限性很明显);性能吞吐量整个较低,如果设计一个单独的数据库来实现 分布式应用的数据唯一性,即使使用预生成方案,也会因为事务锁的问题,高并发场景容易出现单点瓶颈。

适用场景:单数据库实例的表ID(包含主从同步场景),部分按天计数的流水号等;分库分表场景、全系统唯一性ID场景不适用。

redis生成ID

通过Redis的INCR/INCRBY自增原子操作命令,能保证生成的ID肯定是唯一有序的,本质上实现方式与数据库一致。

优点:整体吞吐量比数据库要高。

缺点:Redis实例或集群宕机后,找回最新的ID值比较麻烦。

适用场景:比较适合计数场景,如用户访问量,订单流水号(日期+流水号)等。

UUID、GUID生成ID

优点:性能非常高,本地生成,没有网络消耗;

缺点:UUID 太长了、占用空间大,作为主键性能太差了;

由于UUID 不具有有序性,会导致 B+ 树索引在写的时候有过多的随机写操作

适合的场景:如果你是要随机生成个什么文件名、编号之类的,你可以用 UUID,但是作为主键不建议用 UUID 的。

snowflake(雪花)算法

snowflake算法来源于Twitter,使用scala语言实现,snowflake算法的特性是有序、唯一,并且要求高性能,低延迟(每台机器每秒至少生成10k条数据,并且响应时间在2ms以内),要在分布式环境(多集群,跨机房)下使用,因此snowflake算法得到的ID是分段组成的:

  • 与指定日期的时间差(毫秒级),41位,够用69年
  • 集群ID + 机器ID, 10位,最多支持1024台机器
  • 序列,12位,每台机器每毫秒内最多产生4096个序列号

雪花算法核心思想是:分布式ID固定是一个long型的数字,一个long型占8个字节,也就是64个bit。

  • 1bit:符号位,固定是0,表示全部ID都是正整数
  • 41bit:表示的是时间戳,单位是毫秒。41 bits 可以表示的数字多达 2^41 - 1 ,也就是可以标识 2^41 - 1 个毫秒值,换算成年就是表示69年的时间。
  • 10bit:机器ID,有异地部署,多集群的也可以配置,需要线下规划好各地机房,各集群,各实例ID的编号
  • 12bit:序列ID,用来记录同一个毫秒内产生的不同 id,12 bits 可以代表的最大正整数是 2^12 - 1 = 4096 ,也就是说可以用这个 12 bits 代表的数字来区分同一个毫秒内的 4096 个不同的 id。

优点:

毫秒数在高位,自增序列在低位,整个ID都是趋势递增的。

不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的。

可以根据自身业务特性分配bit位,非常灵活。

缺点:

强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。


 
上一篇 金三银四精选面试题-IP地址如何在数据库中存储?
下一篇 金三银四精选面试题-如何实现 MySQL 的读写分离?MySQL 主从复制原理是啥?如何解决 MySQL 主从同步的延时问题?

文章素材均来源于网络,如有侵权,请联系管理员删除。