面试官:分库分表后,id主键如何处理?

作为一名java程序员,求职面试时,关于主键id的问题时常会遇到,张工是一名java程序员,最近到某知名互联网公司面试,面试官提出这样的一个问题:

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

其实这是分库分表后需要面对的一个问题,因为分成多个表后,我们需要一个全局唯一的 id 来支持。

为什么要分库分表?

随着业务的不断发展,数据量将越来越大,ID作为系统数据的重要标识,重要性不言而喻.如果一个库中的表数据超过了一定的数量,比如说mysql中的表数据达到千万级别,就需要考虑进行分库分表了,

当数据库实例的吞吐量达到性能的瓶颈时,我们需要扩展数据库实例,让每个数据库实例承担其中一部分数据库的请求,分解总体的大请求量的压力;

在数据库进行扩容的时候对应用层的配置改变最少, 就需要在每个数据库实例中预留足够的数据库数量

以上的情况我们都可以使用分库分表,那么什么是分库分表呢?

简而言之就是数据拆分:将一个表数据分片后放入多个表。

那么分库分表后,每个表中的数据都会按自己的节奏进行自增,很有可能出现ID冲突。

基于数据库的实现方案

1、数据库自增长ID

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

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

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

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

2、Redis生成ID

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

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

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

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

UUID、GUID生成ID

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

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

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

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

UUID.randomUUID().toString().replace("-", "")

e444d1431da3403698af9f5d86210527

snowflake(雪花)算法

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

  • 与指定日期的时间差(毫秒级),41位,够用69年

  • 集群ID + 机器ID, 10位,最多支持1024台机器

  • 序列,12位,每台机器每毫秒内最多产生4096个序列号

雪花算法核心思想是:分布式ID固定是一个long型的数字,一个long型占8个字节,也就是64个bit,原始snowflake算法中对于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。

0 | 0001100 10100010 10111110 10001001 01011100 00 | 10001 | 1 1001 | 0000 00000000

优点:

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

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

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

缺点:

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

总结:

snowflake 算法相对其他三个方法来说还是比较靠谱的,要是搞分布式 id 生成,如果是高并发的,那么建议采用这个应该性能比较好,一般每秒几万并发的场景,足够用了。

关于如何生成分布式ID,平时工作中要注意总结和积累,查漏补缺,不断完善自己的知识体系。

拓展:

在大公司里,譬如滴滴,并没有直接使用snowflake,而是对其进行了改造,典型的有:

  • 百度uid-generator 

  • 美团Leaf项目

  • 滴滴(Tinyid)

由于笔者水平有限,文中纰漏之处在所难免,权当抛砖引玉,不妥之处,请大家批评指正。

-END-

作者:洪生鹏  技术交流、媒体合作、品牌宣传请加作者微信: hsp-88ios

猜你喜欢

作为一名程序员,技术的广度与深度如何权衡

终于知道阿里字节这样的大公司,为什么面试时经常拿final来考验求职者了

更多惊喜,请长按二维码识别关注

你若喜欢,别忘了点【在看】

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值