为什么分库分表?
分库分表虽然连在一起,但确实是不同的技术,因此这需要分开来解答。
为什么分库?
分库的原因在于库的并发是有限度的(比如2000)
为什么分表?
分表主要是为了优化sql查询性能
如何拆分?
我们可以想象一个数据库的表,第一行是表的各个字段,下面的每一行的每一列都是字段对应的数据。那么拆分可以很直观的分为按照字段进行拆分的垂直拆分以及拆分行的水平拆分。
垂直拆分
垂直拆分其实我们无意中也做过。比如将一个大的订单表拆分为商品表、订单支付表等。
若是为了更好优化查询性能,我们可以将访问频率高和低的字段拆分,使得高频率字段中的表字段更少,能够缓存更多行,优化查询性能。
水平拆分
- 按照range来分:比如按照月份来分。这种分发扩容比较简单,但是可能会导致并发压力全部集中在几个表中,例如新上架的电子产品相比于好几年前的会有更多人购买,那么对最新产品表就会造成很大的访问压力
- hash分:好处可以平均分配请求压力,但是扩容麻烦。
迁移
停机迁移
这个是最简单的迁移方案,就是先停机,然后倒入旧表数据到新表,接着改数据库配置,改相应的代码,最后验证一下
双写迁移
就是在现有系统上每次对老库数据的更改同时更改到新库,接着从老库中导入新数据或者新库没有的数据,然后验证新旧库数据是否一致,最后就可以部署上线了。
如何处理分库分表之后的主键?
自增ID
可以专门建一个表,存储所有表的主键,每次插入数据的时候,取该表的自增ID作为新插入数据的id。当然,这对于高并发简直是灾难。就算搞出一个服务取id,递增几个,返回一批,也很难说有很大的改善。
UUID
这个可以基于本地生成,可是对于数据库的主键来说,性能太差。
时间戳
就是以当前的时间戳作为id,可是要是一秒并发几千的话,也会重复
SnowFlake算法
twitter开源的分布式id生成算法,有一个64位的long型id。
- 1bit:统一为0,因为id要为正数。
- 41bit:表示时间戳,单位是毫秒
- 10bit:代表工作机器id
- 12bit:在时间戳相同的情况下,用于区别同毫秒内4096个不同id
Ref
- https://blog.csdn.net/weixin_43314519/article/details/109823130