1. 主从复制
1.1. 优点
- 做数据的热备。主数据库故障后,可切换到从数据库继续工作,避免数据丢失
- 架构的扩展。业务量增加,单机无法满足,做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能
- 读写分离。使数据库能支持更大的并发量
1.2. 原理
主从数据库之间通过binary log进行数据的同步
binary log有三种模式
基于SQL语句的复制(STATEMENT)
MySQL 会将执行的每个更改数据的 SQL 语句(insert、update、delete)记录到二进制日志中,进而同步到从库的relaylog中,被从库的SQL线程取出来,回放执行
优点:
- 效率高:因为只记录 SQL 语句,所以日志量相对较小。
- 易读性:日志内容是标准的 SQL 语句,便于阅读和调试。
缺点:
- 非确定性语句问题:同步的SQL语句里如果包含有某些函数、关键字等,在执行时可能会产生不同的结果,例如基于 NOW() 或 RAND() 函数的语句。
基于行的复制(ROW)
MySQL 会记录每一行的改变,更新前和更新后的数据,而不是记录 SQL 语句,可以保证主从数据绝对相同
优点:
- 准确性高:每一行的变化被精确记录,消除了非确定性语句可能带来的问题。
- 复制一致性:适用于复杂的数据修改,如涉及触发器、存储过程等的操作。
缺点:
- 日志量大:因为记录了每一行的变化,所以日志量可能非常大,尤其是在进行批量操作时。
- 可读性差:日志内容是行数据的变化,不易阅读和调试。
混合复制
以上两种模式的混合,MySQL 会根据具体的 SQL 语句类型自动选择使用 STATEMENT 或 ROW 模式。通常,会优先使用 STATEMENT 模式,但在某些情况下(如非确定性语句)会切换到 ROW 模式。
1.3. 同步模式
MySQL主从同步的同步模式
全同步
全同步复制确保每一个写操作在所有从数据库都确认接收到更改后,主数据库才返回给客户端。
优点:最高的数据一致性:确保所有从数据库都接收到更改,完全消除了数据丢失的风险。
缺点:性能显著降低:主数据库需要等待所有从数据库的确认,写操作的延迟显著增加。
半同步
在半同步复制中,主数据库在将更改写入二进制日志后,会等待至少一个从数据库确认接收到该更改,然后才返回给客户端。
优点:提高数据一致性:在主数据库崩溃时,只有确认至少一个从数据库接收到更改,才返回给客户端,从而减少了数据丢失的风险。
缺点:性能影响:由于主数据库需要等待从数据库的确认,写操作的延迟增加,可能会影响性能。
异步
异步复制是 MySQL 默认的复制模式。在异步复制中,主数据库在将更改写入二进制日志后立即返回给客户端,而不等待从数据库的确认。
优点:性能高:因为主数据库不需要等待从数据库的确认,所以写操作的延迟很低。
简单实现:配置和管理相对简单,适用于大多数常见场景。
缺点:潜在的数据丢失:在主数据库崩溃时,可能会有一些操作还没有被复制到从数据库,从而导致数据丢失。
2. 读写分离
主数据库负责数据的写操作,从数据负责数据的读操作
2.1. 实现
- 应用层实现:应用程序代码中区分读写操作,并根据操作类型选择连接主库或从库。
- 中间件实现:如 sharding-jdbc 等中间件,可以自动实现读写分离。
3. 分库分表
3.1. 分表(分片)
将一张大表分成若干小表
垂直切分
垂直切分是将一张表中的列数据按逻辑关系分散到多个表中,每个表存储部分列的数据。常见的垂直切分策略包括将经常访问的列和不常访问的列分开,将大字段和小字段分开等。
水平切分
水平切分是将一张表中的行数据按某种规则分散到多个表中,每个表都有相同的列结构,但存储的是不同范围的数据。常见的水平切分策略包括按范围(Range Sharding)、按哈希(Hash Sharding)等。
3.2. 分库
将多种分类的数据表,分开存在不同的数据库中,如:用户数据,订单数据,商品数据,分别放在不同的数据库中。有利于差异化管理
3.3. 实现
在分库分表的同时要解决使用的透明度,在应用程序和数据库集群中增加数据库代理层如:sharding-jdbc ,降低应用程序和数据库间的耦合度
3.4. 分库分表方案产品
目前市面上的分库分表中间件相对较多,其中基于代理方式的有MySQL Proxy和Amoeba, 基于Hibernate框架的是Hibernate Shards,基于jdbc的有当当sharding-jdbc, 基于mybatis的类似maven插件式的有蘑菇街的蘑菇街TSharding, 通过重写spring的ibatis template类的Cobar Client