数据库库表分离

读写分离:

由于用户的增多,数据的增多,单机的数据库往往支撑不住快速发展的业务,所以数据集群就产生了。

读写分离就是读和写分离了,对应到数据库集群一般都是一主一从,或者一主多从。业务服务器把需要写的操作都写到主数据库,读的操作都去从库查询。主库会同步数据到从库保证数据的一致性。
集群方式的本质就是把访问的眼里从主库转移到从库

在单机的情况下,一般我们做数据库优化都会加索引,但是加了索引对查询有优化,但是会影响写入,因为写入数据会更新索引。所以做了主从之后,我们可以单独的针对从库做索引上的优化,而主库可以减少索引而提高写的效率。
有两点需要注意:主从同步延迟,分配机制的考虑;

主从同步延迟

主库有数据写入之后,同时也写入在binlog中,从库是通过binlog文件来同步数据的,这期间会有一定时间的延迟,如果同事有大量数据写入的话,时间可能更长。
解决主从同步延迟问题的方法:

  1. 二次读取:意思就是读从库没读到之后再去主库读一下
  2. 写之后的马上读操作访问主库
  3. 关键业务读写都由主库承担,非关键业务读写分离
    从主集群就是读写分离,分担了访问的眼里,但是存储的压力没有解决。

分库分表

分库

分库可以将存储压力分担多个服务器上,但是会带来新的问题,所有的东西变复杂都会有新的问题产生

  1. 联表查询
    join,之前在一个数据库里面可以用join来进行关联查询,但是现在分了多个数据库,join就用不上了。
  2. 事务问题
    数据库操作基本都离不开事务,但是现在不同的数据库事务就不是以前的那个简单的本地事务了,而是分布式事务,而引入分布式事务也就提高了系统的复杂性。

分表

分表:就是一张表按照一定的规则分解成多个独立的实体表,系统读写时需要根据定义好的规则得到对应的子表名,然后操作它。
分表分为垂直分表和水平分表

1) 垂直分表:垂直分表适合表中存在不常用并且占用了大量空间的字段拆分出去。

垂直分表影响就是之前只要一个查询的,现在需要两次查询才能拿到分表之前的完整数据信息。

2) 水平分表:水平分表就是适合表行数很多的情况,一般单表行数超过5000万就得分表。当一个表行数超过千万级别的时候,关注一下,如果没有性能问题就可以在等等看,不要急着分表,因为分表会带来更过的问题。
一般分表看路由

  1. 按照id,也就是范围路由。这种分法的好处是容易切,简单粗暴,以后新增的数据分表都不会影响到之前的数据,之前的数据都不需要移动。
  2. 哈希路由 就是取几列哈希一下看看数据哪个库,比如拿id来做哈希。这种分法好处是分的很均匀,基本上每个表的数据都差不多,但是以后新增的数据又得分表了怎么办,以前的数据都得动,比较麻烦。
  3. 搞一张表来存储路由关系,这种方式也简单,之后又要分表了之后改改路由表,迁移一部分数据。但是这种方法导致每次查询都得查询两次,并且如果路由表太大了,那路由表又成为瓶颈了。

分库分表之后面临的问题

  1. 事务支持
    分库分表之后,就成了分布式事务了,如果依赖数据库本身的分布式事务管理功能区执行事务,将付出高昂的性能代价;如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程上的负担。
  2. 多库结果集合并(group by order by)
  3. 跨库join
    分库分表后,表之间的关联操作将受到限制,我们无法join位于不同分库的表,也无法join分表粒度不同的表,结果原本一次查询能够完成的业务,可能需要多次查询才能完成。粗略的解决方法,
    全局表:基础数据,所有库都拷贝一份。
    字段冗余:这样有些字段就不用join去查询了。
    系统层组装:分别查询出所有,然后组装起来,较复杂。
  4. 分库分表方案产品
    目前市面上分库分表中间件想对较多,其中基于代理方式的有Mysql Proxyhe Amoeba,基于Hibernate框架的是Hibernate Shards,基于JDBC的有当当的sharding-jdbc,基于mybatis的类似maven插件式的有蘑菇街的蘑菇街TSharding,通过重写spring的ibatis template类的Cobar Client。