垂直(纵向)拆分:将一个库的多个表分散到多个库,或将一根表拆分成多个表,再分散到多个库
水平(横向)拆分:将一个表的数据,分散到同一仓库的多个表,或分散到不同仓库的多个表,或分散到不同数据库的多个表
水平拆分带来的问题(不能解决则避免出现这些需求):
1、分布式事务问题
2、跨节点连接查询问题
3、跨节点排序分页问题
水平分片实现方式
1、客户端分片
在SQL中拼接表名,以MyBatis为例
<select id="getUser" parameterType="java.util.Map" resultType="User">
SELECT userid,username FROM USER_#{index} WHERE userid=#{userid}
</select>
工具例子:当当Sharding JDBC等
优点:简单,易定位问题
缺点:侵入业务
2、代理分片
工具例子:奇虎360 Atlas、Mycat等
优点:非侵入
缺点:影响性能,难定位问题
3、分布式数据库
工具例子:MySQL Cluster等
水平分片的分片维度
1、哈希分片:所属分片 = hash(数据的某字段) % 分片总数
优点:均匀
缺点:分散
2、按照时间进行分片
适用:有明显时间特征的数据
主从复制(实时备份)Replication
意义:读写分离的基础
一、基于日志点的复制
原理步骤:
1、主服务器(master) 记 二进制日志
2、从服务器(slave)的I/O进程 向 主服务器发出日志请求
3、主服务器把自己的二进制日志(binary log)信息返回给 从服务器的I/O进程
4、从服务器的I/O进程 把得到的日志信息追加到自己的 中继日志(relay log)
5、从服务器的SQL进程 检测到中继日志变化,批量执行 日志记录
特点
1、是异步复制,读写分离时,slave的数据会有延迟;解决方案:避免立即读取,特定用户从master读
BinLog的格式
Statement:存SQL语句,缺点:同一条SQL语句在主从服务器上执行的结果可能不一样,造成不一致
Row:存对每一行的修改记录,缺点:不可读,记录量大
Mixed:执行结果不确定的操作存成Row格式,否则存成Statement格式
步骤
1、在master上创建slave账号并授权:create user 'user1'@'ip' identified by 'pass'; grant replication slave on . to 'user1'@'ip';
2、备份master的所有db:mysqldump --single-transaction --master-data=2 --triggers --routines --all-databases > ~/dump.sql;
# --single-transaction 单独线程做导出,--master-data=2 不导出本节点的跟随信息
# --triggers 导出触发器, --routines 导出存储过程
3、在slave上恢复:mysql -uroot -p < ~/dump.sql;
4、在slave上配置跟随的master:change master to master_host='ip',master_user='user_1',master_password='pass',
master_log_file='mysql_bin.00004',master_log_pos=1687;
# master_log_file 即master的最新一个binlog文件,即dump.sql里的MASTER_LOG_FILE
# master_log_pos 即master备份dump.sql时的最后一个日志点,即dump.sql里的MASTER_LOG_POS
5、查看slave状态:show slave status; 关注Slave_IO_Running 和 Slave_SQL_Running
slave相关操作
停止跟随:stop slave;
replication配置和状态相关表:use performance_schema; replication_开头的几个表
更改复制延迟时间(秒):change master to master_delay=3600; # 每小时同步一次
多线程复制:set global slave_parallel_type='logic_clock'; set global slave_parallel_workers=4; # 多线程用于 执行relay log,个数可以设置为db个数
开始跟随:start slave;
二 、基于事务ID的复制
GTID:Global Transaction Identifier,全局事务标识符,即事务ID
问题:基于日志点的复制,主从的binlog是不一样的,日志点也不一样,master故障时,要在slave中选举一个master,但是slave之间无法知道对方的日志点
方案:在binlog中记录事务ID,主从记录的事务ID都是一样的,master故障时,可以在slave中选举合适的master
步骤
1、主从上分别配置
enforce_gtid_consistency=on;
gtid_mode=on;
2、在slave上:change master to master_auto_position=1;
基于日志的复制改为基于事务的复制
0、前提是 show variables like 'gtid_mode'; 为 OFF
1、在主从上分别 set @@global.enforce_gtid_consistency=warn;
2、在主从上分别 set @@global.enforce_gtid_consistency=on;
3、在主从上分别 set @@global.gtid_mode=off_permissive;
4、在主从上分别 set @@global.gtid_mode=on_permissive;
5、在主从上分别 set @@global.gtid_mode=on;
6、在slave上:stop slave;change master to master_auto_position=1;start slave;
三、多源复制
一个slave可以从多个master复制不同的db或table
其他主从复制方案
一、PXC(Percona XtraDB Cluster)
对比Replication:PXC方案中,数据完全同步后,才返回操作成功;PXC能保证强一致性,读写分离时从库数据不延迟,但性能较差
二、MHA(Master High Availability)
对比Replication:主服务器出现故障时,可以实现主从切换
阿里云
分布式关系型数据库服务 DRDS:ID采用DRDS Sequence,全局唯一,有序递增的数字序列。将来要导入DRDS的数据,ID最好就是自增数字序列