分库分表理论

1、分库分表的原因

 关系性数据库易成为系统性能瓶颈、单机存储容量、连接数、处理能力等都很有限,而数据的四大特性要求又导致了数据库没法向web应用服务器那样易于扩展,在大数据量情况下就有了分库分表(也成为Sharding、分片),流行的分布式系统中间件(MongoDB、ElasticSearch等)均可以友好的支持Sharding。

2、分库分表的原则

       能不分就不分:因为数据库表之间的关联也映射了业务逻辑,任何分库分表行为都会倒置业务更加复杂;而且分库分表之后还要涉及到做业务时数据的合并、查询或更新等多种问题;所以能从升级硬件、网络、读写分离、负载均衡解决的就不要使用分库分表;

(1)影响数据库的备份,单表或单个实例太多;

(2)数据量大到对数据库做ddl操作时会锁住全表,这个期间会影响业务正常访问;

(3)数据访问和更新频繁,经常导致死锁,但是却没有能力修改源码拉解决,那么只能降低锁的粒度;

(4)表设计不合理,需要对某些字段垂直拆分;

比如一张user表:

id   用户id

name  用户姓名

last_login_time 最近登陆时间

personal_info  私人信息

该表的用户数从100w飙升到1亿,在用户登陆时需要频繁的更改last_login_time,导致数据库压力非常大,那么就可以做垂直拆分,把该字段拆分出去;如果做水平拆分,那么是没有作用的,因为修改时还是需要做每一张表做修改;

(5)某些数据表无穷增长:水平拆分;

 (6)安全性和可用性考虑

       如果数据库出现问题,那么希望不要影响到100%的用户,希望能够降低这个影响,那么可以做水平切分,如:把用户、订单、库存等本来在同一资源库的进行切分。每个小的数据库实例承担一小部分业务,以此提高整体的可用性;

 (7)业务耦合性

      如购买火车票 和点外卖这样不同的业务,可以放在不同的库催触;

3、分库分表方案

(1)垂直拆分

   垂直拆分有:垂直分库和垂直分表,垂直分表较常见如:大表拆小表;该拆分是基于“列(字段)”进行的,可以将不常用的字段拆分到另一个表中,垂直拆表如下:

这种拆分也能避免查询时“跨页”的问题,因为mysql底层是通过“数据页”来存储的,“跨页”也会带来额外的性能开销

垂直拆库:

在微服务中按照业务模块来划分出不同的数据库,也是一种垂直拆库的做法。如在电商服务中,将整个业务分为:用户库、订单库、库存库等;

 a、垂直拆分的优点

    使数据行数变小,一个数据块就能存储更多的数据,可以减少查询时I/O次数(每次查询的block块会减少);

最大化利用cache,拆分时可以将不常变的字段放在一起,经常变的放在一起;

数据库的连接资源比较宝贵而且单机处理能力也有限,在高并发情况下,垂直分库一定程度上能突破IO、连接数及单机资源的瓶颈;

 b、垂直拆分的缺点

  主键冗余、表之间的join(增加cpu开销)可通过在业务服务器上进行join来减轻数据库压力;

 依然存在单表数据量过大的问题(需要水平拆分)、事务处理复杂;

(2)水平拆库

     通过某种策略将数据分片存储,分为库内分表和分库分表两部分,每片数据会分散到不同的MySql表或者库上;

库内分表:仅仅解决了单一表数据过大的问题,并没有把数据分布到不同的机器,对于减轻mysql服务器的压力来说并没有太大的作用,还是需要竞争同一物理机上的IO、CPU、网络;对于该问题通过分库分表即可解决;

分表有【静态分表】和【动态分表】:

静态分表:提前计算好需要分多少张表,根据hash值来计算;

动态分表:避免了静态分表的后遗症,在系统中使用“冷热数据分离”(将一些历史数据迁移到其他的数据库中,在业务上只提供热点数据的查询),分库分表能够有效缓解单机和单库的性能瓶颈和压力;

缺点:分片事务一致性难以解决;跨节点join 性能差,逻辑复杂;数据多次扩展难度与维护量大;

解决跨库join的问题:

(1)全局表:将这类表在其他每个数据库中均保存一份,同时这种数据几乎很少发生修改;

(2)字段冗余:是一种以空间换时间的做法,比较适合依赖字段少的情况;

 (3)数据同步:定时a库中的tab_a 表和b库中的tab_b有关联,可定时将指定表做同步,通常使用etl来实现;

解决跨库导致的分布式事务问题:通过xa接口和两阶段提交完成;

4、常见分片规则和策略

(1)分布式全局唯一id的生成策略

       1. Twitter的Snowflake(又名“雪花算法”)

        2. UUID/GUID(一般应用程序和数据库均支持)

        3. MongoDB ObjectID(类似UUID的方式)

        4. Ticket Server(数据库生存方式,Flickr采用的就是这种方式)

(2)分片字段如何选择:选择最频繁被使用或者最重要的字段来作为分片字段;常见的分片策略有“随机分片”和“连续分片”两种;

(4)数据迁移、容量规划、扩容等问题

对历史数据分片:一般做法是通过程序先读出历史数据,然后按照指定的分片规则将数据写入到各个分片节点中,一般单个分片上的单表数据量不超过1千万;如果采用随机分片则要考虑扩容,如果采用范围分片则只需添加节点就可以自动扩容

5、分库分表组件Sharding-JDBC介绍

(1)、应用层分还是中间层分?

应用层可以在JDBC驱动层、DAO层,如:iBatis/Mybatis /JPA上完成,

如当当的sharding-jdbc是jdbc驱动层实现,而阿里的cobar-client是基于dao层框架ibatis实现的

你可能感兴趣的:(分库分表理论)