一. 背景
主流架构一般分库分表都会涉及,追求性能的同时,带来各种痛点。
比如订单id的生成,在分表的情况下,使用int自增,两张分表都自增,直接会导致主键ID的重复,这是错误。
补充常见的分库分表中间件:
1. DB层次的,针对DB做代理。
ShardingSphere-Proxy的架构图
2. 代码层次的
最常见的是 sharding-jdbc (他和 shardingsphere-proxy是同一产品下的东西,只是作用的层次不同),如下图:
二者的区别详见:https://shardingsphere.apache.org/document/legacy/3.x/document/cn/overview/
二. 方案剖析
1. 自增方案
方案1:起始点分段
比如设置分表2的起始点从10000开始
ALTER TABLE incorder_1 AUTO_INCREMENT=10000;
优缺点:
简单容易,数据库层面设置,代码是不需要动的
边界的切分人为维护,操作复杂,触发器自动维护可以实现但在高并发下不推荐
方案2:分段步长的自增
--查看
show session variables like 'auto_inc%';
show global variables like 'auto_inc%';
--设定自增步长
set session auto_increment_increment=2;
--设置起始值
set session auto_increment_offset=1;
--全局的
set global auto_increment_increment=2;
set global auto_increment_offset=1;
分析:
影响范围不可控,要么session每次设置,忘记会出乱子。要么全局设置,影响全库所有表
结论:不可取!!!
方案3:Sequence特性
-- 创建一个sequence:
create sequence sequence_name as int minvalue 1 maxvalue 1000000000 start with 1
increment by 1 no cache;
-- sequence的使用:
sequence_name.nextval
sequence_name.currval
-- 在表中使用sequence:
insert into incorder_0 values(sequence_name.nextval,userid);
2. 基于业务规则自定义生成
不用自增,自定义id,加上业务属性,从业务细分角度对并发性降维。例如淘宝,在订单号中加入用户id。
加上用户id后,并发性维度降低到单个用户,每个用户的下单速度变的可控。
时间戳+userid,业务角度,一个正常用户不可能1毫秒内下两个单子,即便有说明是刻意刷单,应该被前端限流。
3. 集中式分配
4. uuid和guid
5. 雪花算法
详见下面
三. 雪花算法
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。