likes
comments
collection
share

分表分库

作者站长头像
站长
· 阅读数 14

分表分库

分表分库

垂直分表

简单来说就是拆表,将一张表的字段拆分到多个表中。

这样可以减少对同一条记录但是不同字段的争抢,提升性能。注意text,blob字段这样的大字段,尽量和热点数据区分,避免读取热点数据时和text这样占用大量空间的字段在一张表中,因为text这样的字段占用空间大,造成跨页IO读取,影响热点数据读取性能。

水平分表

水平分表解决单张表数据量过大的问题,将一张表中的数据按路由规则划分到不同表中。水平分表提升了单张表的IO性能,但是仍受数据库实例的IO性能制约。

分表分库

常用的路由方式有字段hash或者字段映射等。字段hash数据分配的较为平均,避免分表后数据倾斜;也可以对表中时间或者地区等字段作为路由依据,一段时间一张表或者一个地区一张表,但是这样难以应对突发的流量暴增导致数据倾斜。

水平分表后,造成分页排序失效,必须全表扫描都已经这么大数据还分什么页。 对于查询条件中,没有路由信息的,那么也会全表扫描。例如现在已经按照地区(region)分表,但是where条件中不含有region字段,而是要查询指定name,那么就会走全表扫描。 分表之后还可能造成分布式事务的出现。(暂时没有例子)

垂直分库

和垂直分表差不多,原有数据库实例中可能含有不同模块的表,一旦某个模块出现流量上升,就会牵连其他模块性能。为了提高可用性,将不同模块表迁移到各自专属的数据库实例。

水平分库

水平分库提升数据库IO性能,过程和水平分表差不多。

分表分库

分表分库的分布式问题

分表分库带来性能提升,但是也会引入分布式问题。原来单表主键依靠一个自增序列就可以解决,但是分布式场景下,就需要额外引入全局唯一性主键来避免不同表中主键冲突。

  • 使用同一自增序列 不同表都使用一个自增序列,这样就可以避免主键冲突。但是所有表依赖一个序列有单点问题,影响可用性,不推荐
  • 预留主键id 给每张表预分配一段id。如table1主键在区间1000-1999,table2主键在区间2000-2999,避免主键冲突。但是这样存在诸多隐患,不能应对突发流量,一旦预留资源耗尽就需要手动修改。
  • 雪花算法
  • UUID

此外,路由的逻辑也需要引入到应用中。在客户端引入路由称为客户端分库如sharding-JDBC,还有额外引入代理的proxy分库如Mycat和TDDL。还有自己算表名然后拼上去

读写分离

除了做分表分库之外,还可以设计数据库实例进行读写分离,master实例负责写入,slave负责读取,提升数据库性能。

MySQL主从复制和Redis主从差不多,master节点记录每一条写入操作到binlog文件中,并入slave节点后将binlog发过去,slave再进行数据同步。

分表分库

MySQL默认采用异步复制,不要求主从强一致而是最终一致。master节点写入即认为成功,不考虑slave是否接收并同步。

分表分库

如果想要集群强一致,那么可以采用半同步方式,除master写入成功外,还要求半数slave节点接收并成功同步,这时才会向client返回成功。

分表分库

参考文献: [1]: 一次分表踩坑实践的探讨