一、高并发的场景下ID生成有哪些规则要求?
1.全局唯一
2.生成效率要高
3.趋势递增(从小到大)
二、可行性方案有哪些,各自的有点和缺点有哪些呢?
1.UUID方式生成主键
优点 | 缺点 |
---|---|
1.使用简单 | 1. 数据库索引效率较低 |
2.不依赖其它主键 | 2. 太过于无意义,对用户来说不友好 |
3.不影响数据库的拓展 | 3. 长度36的字符串,空间占用较大 |
4. 作用于集群环境,机器多的时候,重复几率较大 |
2.数据库自带的increment或者sequence方案生成主键
mysql使用自带的auto_increment
oracle,DB2使用sequence序列
集群环境下,不同的库,使用不同的初始值,设置固定的步长,从而达到ID的唯一性。
比方说:
XX_1这个表,我设置成以1开头的自增属性,每次自增100;那么XX_1这张表的ID就是1,101,201,301这样;
XX_2这个表,我设置成以2开头的自增属性,每次自增100;那么XX_1这张表的ID就是2,102,202,302这样
这样就在分表小于100的情况下,每个ID都会是独立的;
具体的mysql设置起点和步长方式的命令如下:
set @@auto_increment_offset = 1;//设置初始值
set @@auto_increment_increment=100;//设置步长值为100
show variables like ‘auto_inc%’;查询设置的参数
优点 | 缺点 |
---|---|
1.无需编码 | 1.依赖前期规划,拓展麻烦(比方说我前期设置为512张库,后期万一需要扩容,很麻烦) |
2.性能一般 | 2.依赖mysql内部维护的“自增锁”,高并发下插入数据比较麻烦,有瓶颈 |
3.索引友好,都是数字,效率比较高 | 3.在执行业务操作时,要"先父后子"。(必须先插入附表有了ID,字表才能关联到) |
3.twitter雪花算法生成主键
雪花算法的实现:网上实在是太多了,大家可以看下。
当然大厂也对雪花算法实现了一些增强,包括百度,美团,大家可以看下。
优点 | 缺点 |
---|---|
1.性能较优,速度较快 | 依赖机器的时间 ,如果发生回拨,会导致ID重复,当然大家可以对雪花算法进行一些优化 |
2.无需依赖第三方,实现起来也比较方便,容易 | |
3.可控性强,可以根据自己的实际业务的情况,调整和拓展算法,方便灵活 |
解释:
有人会对第一条产生疑问:性能较高,速度较快。雪花算法不是带synchronized关键字了,意味着同一个时间内只有有个线程可以执行操作。效率不是有点影响吗?
其实不是,单台机器处理服务器也有一些应用极限。比方说单台机器的TPS强如redis也只是10wTPS+;但是雪花算法一秒钟理论上生成的ID的数量接近400W+;所以性能上是没有问题的。
4.基于Redis方案实现主键的自增
Redis方案如何实现呢?
Redis有个自增长计数器API,在配合一些其它的信息可以组装成为唯一ID;
主要有Redis的自增函数incr(Key);
而且使用Redis还有个好处:Redis本身就是单线程的,自增计数API,数据有效期机制。
优点 | 缺点 |
---|---|
1.拓展性强,可以方便的结合业务进行处理 | 1.引入Redis就意味者引入其它的第三方依赖 |
2.利用Redis操作原子性的特性,保证在并发的时候不会重复 | 2.增加多次的网络开销(因为要做主从同步) |
3.需要对Redis服务实现高可用 |
各自的优劣势对比
策略 | 优点 | 缺点 | 推荐指数 |
---|---|---|---|
UUID | 实现简单,不占用宽带 | 无序,占用空间,可读性差,索引不友好 | 1 |
数据库自增 | 无代码调整,递增 | DB单点故障,扩展性差 | 4.5 |
雪花算法 | 性能优,不占用宽带,趋势递增 | 依赖服务器时间 | 4.5 |
Redis自增 | 无单点故障(高可用之后),性能优于DB,递增,灵活性强 | 占用带宽,集群维护 | 4.5 |
三、选择哪种方案比较好呢?
除了第一种方案不推荐外,其它3种情况视各自的应用场景而定。其中数据库自增我觉得已经满足大部分的应用场景;
四、淘宝,天猫的技术架构又是如何的呢?
后面再聊。
参考来源:《Java高级开发工程师》 网易云课堂