单机到集群
mysql技术演进
读写压力->多机集群->主从复制
高可用性->故障转移->MHA/MGR/Orchestrator
容量问题->数据库拆分->分库分表(垂直拆分-按业务拆分,水平拆分-)
一致性问题->分布式事务->XA(强一致性)/柔性事务
主从复制
- 主库写binlog
- row 行:会记录每一行的修改,比较详细
- Statement:记录sql本身,
- Mixed:混合模式
- 从库relay log
复制方式
- 异步复制:网络或机器故障,会导致数据不一致.主库在执行玩客户端提交的事务后会
mysql读写分离
应用侧需要配合读写分离的框架
解决方法:
- 创建多个dataSource
- 使用AbstractRoutingDataSource 和自定义注解 readOnly
如果在一个事务中,有写也有读,写完主库后立刻读从库,会因为延迟的问题导致从库还没有更新 - ShardingSphere-jdbc的Master-Slave功能
- sql解析和事务管理,自动实现读写分离(当一个事务中有写有读,则都走主库)
- 使用MyCat/ShardingSphere-Proxy的Master-Slave功能
- 需要部署一个中间件,规则配置在中间件(mysql的中间件对外就是一个数据库)
解决高可用问题
定义:高可用意味着更少的不可服务事件,一般用SLA(服务水平协议)/SLO衡量
- 手动改成某个从节点(有可能数据不一致,对代码有侵入性)
- 用 LVS+Keepalived 实现多个节点的探活+请求路由,配置 VIP 或 DNS 实现配置不变更。
- MHA是一套优秀的作为 MySQL 高可用性环境下故障切换和主从提升的高可用软件。
- MGR如果主节点挂调,将自动选择从节点改成主,
为什么要高可用
故障转移,灾难恢复
容灾:热备与冷备(指从机在日常中不工作,只有当主机挂掉,从机才会启动)
对于主从来说,简单来说就是主挂,某一个从,变成主
数据库拆分与分库分表
为什么要做数据库拆分
- 数据库过大的问题
- 执行DDL语句会很慢
- 备份时会锁整个库
- 主备延时会很高
- 主从解决了高可用,读扩展,但单机容量不变,单机写性能无法解决。
- 提升容量->分库分表-,分布式,多个数据库降低单个节点的写压力
- 扩展立方体(扩展系统的3种方式)
- X轴:通过克隆整个系统,集群(主从结构,备份和高可用)
- Y轴:通过解耦不同功能复制,业务拆分(垂直分库分表,分布式服务化,微服务->受业务数量限制)
- Z轴:通过拆分不同数据扩展,数据分片(水平分库分表,将一个表中的数据垂直切分放到多个库中)
数据库垂直拆分
- 垂直分库分表=>分布式服务化=>微服务架构
- 拆库:将一个数据库,拆分成多个提供不同业务数据处理能力的数据库
- 拆表: 如果单表数据量过大,还可能需要对单表进行拆分
- 数据孤岛-数据仓库-数据集市-数据湖
优点:数据库变小容易维护,提示性能和容量,改造后系统和数据库复杂度降低,可以作为微服务改造的基础
缺点:库变多管理变复杂,对业务系统有较强的侵入性,改造过程复杂,
数据库水平拆分
水平拆分:分库,分表,分库分表
例如:使用用户id作为分库键,建立8个数据库按照%8的方式分库,在每个库中将订单分成8个表.必须要有分片键.
- 按照分片键分
- 按照日期分
- 强制按条件指定分库分表
- 自定义分库分表
为什么不建议分表,只建议分表? - 分表不解决容量和io的问题
- 可以用分库代替分表
分库还是分表?
如果dbms读写压力大,则分库;如果只是单表数据量大,则分表
有一个问题:如果
user_id%2分库
user_id%2分表
那么4就会进入db0库,t_0表,5会进入db1,t_1.只会进入这两个库和表中,造成数据的偏移.
相关框架和中间件
java框架:
- TDDL
- ShardingSphere-JDBC
中间件(对应用系统透明,使用中间件就像直接用数据库一样) - ShardingSphere-Proxy
- MyCat/DBLE
- Cobar
- Vitness
- KingShard
- DRDS
C(数据库一致性)A(高可用性)P(大规模集群)
如何做数据迁移
- 全量数据导出:业务停机,数据库迁移校验一致性,业务系统升级
- 依赖数据本身的时间戳:先同步数据到最近的时间戳,在停机维护,增量同步数据
- binlog+全量+增量
- 数据库迁移工具:ShardingSphere-scaling需要和zk配合使用