5、数据库读写分离和分库分表
大约 5 分钟
1.读写分离
1.1 什么是读写分离
读写分离就是数据库的读和写是分开操作的,这样可以大大提高读的效率,也可以提高一些写的效率
1.2 如何进行读写分离
一般来说,可以使用多数据库来进行读写分离,即主从模式,主数据库做为写的数据库,其他数据库做读的数据库。
在应用层,可以通过代理的方式,根据不同的操作转发到不同数据库进行操作,比如MySQL Router。
1.3 主从同步怎么做
- 从数据库向主数据库发出同步请求
- 主数据库给从数据库发送binlog
- 从服务器解析binlog,写入relay log中
binlog是二进制日志,这里面包括了数据库的操作内容,可以根据这里面的内容进行数据同步,也可以通过binlog进行数据库崩溃后的恢复。
1.4 主从延时
主从延时是主数据库的操作没有及时同步到从数据库。
如果要避免主从延时,可以在发现主从数据库内容不一致时,转到主数据库进行读。
1.4.1 哪些情况可能会导致主从延时
- 网络波动。主从数据库之间网络状态不好
- 从数据库性能不好。接收到的binlog无法很快的解析完成
- 事务太大。事务太大,会导致从数据库执行比较慢
- 从库太多。主数据库吞吐量有限,无法很快完成大量的从数据库同步。
2.分库分表
2.1 什么是分库分表
数据库的分库分表就是把数据分配到不同的数据库或者表当中去,以增加读写维护的效率
对于分库来说,我们可以垂直分库,比如现在有一个学生表、课程表、成绩表,我们可以把这三个表分别放到不同的数据库当中。也可以水平分库,比如根据分片键把不同的id分到不同的数据库当中
对于分表来说,我们可以垂直分表,比如我们可以把一个数据库当中不同的列分为不同的表。也可以垂直分表,比如根据分片键来把一个表中的内容分配到多个表当中去。
一般来说水平分库和水平分表是同时进行的。
2.2 什么时候需要分库分表
- 分库 对于分库来说,一般是数据库中的数据量太大了,数据备份时间很长
- 分表 对于分表来说,一般是表数据量太大了,一般超过1kw
2.4 分片算法、分片键
2.4.1 分片算法
- 哈希分片。可以根据分片键的哈希值来决定把数据放到哪个数据库当中去。优点就是随机查找时可以几乎分散到所有数据库当中。缺点就是不支持范围查找,对于后续的数据库扩容可能不是很方便。
- 范围分片。范围分片就是根据分片键所在的范围给数据放到不同的数据库当中去。优点就是支持范围查找,对后续的扩容也比较容易。缺点就是随机查找时可能会集中在某一数据库当中。
- 映射分片。映射分片就是新建一个映射表,把分片键所在的数据库记录下来。映射分片的底层分片方式可以选择哈希分片,也可以选择范围分片。缺点就是需要额外维护一个映射表。
2.4.2 分片键的选择
分片键的选择需要保证以下内容:
- 稳定。一旦确认,不能发生变化。
- 可支持扩容。后续需要扩容,分片键仍然可以再进行分配。
- 离散。 分片键应该可以把数据分散到不同数据库当中,而不是会集中在某个数据库。
一般来说,可以根据表中的某个id来确定。
2.5 分库分表带来的问题
- 不支持join。join操作可以把多个表中的内容拼接在一起返回,但是一旦进行分库之后,数据在不同的数据库当中,可能没有办法进行拼接操作。实际上,一些专家也不推荐使用join,因为性能不佳,可以分别查询然后在上层进行拼接。
- 不支持group by,order by,这些原本在同一表中的操作,分到多个数据库中无法进行了,只能是交给上层进行操作。
- 事务问题。对于传统的事务来说,都是为单表设计的,如果是多数据库,可能无法保证多事务的原子性和隔离性等特点,所以需要考虑分布式事务。
- 分布式ID。在单表中,我们很容易通过自增主键等方式来保证id的唯一性,但是,在多表多数据库当中,我们无法通过这些方式来保证id是唯一的,所以需要考虑分布式ID。
2.6 分库分表后数据如何迁移
- 停机维护 这是一个比较简单常用的方式。我们可以选择一个用户访问量比较小的时间,发个公告停机维护。在停机维护期间,可以进行旧数据库向新数据库的迁移。
- 不停机迁移 这个比较复杂。用户的操作仍然会在旧数据库进行,而新数据库的同步也在进行。直到新旧数据库同步完成,用户的访问会被切换到新数据库。这个过程往往需要binlog的配合。
2.7 分库分表推荐方案
shardingsphere。