1 停机方案
- 发布公告
- 停止服务
- 离线数据迁移(拆分,重新分配数据)
- 数据校验
- 更改配置
- 恢复服务
- 回滚预案
2 停写方案
- 支持读写分离
- 升级公告
- 中断写操作,隔离写数据源(或拦截返回统一提示)
- 数据同步处理
- 数据校验
- 更改配置
- 恢复写操作
- 数据清理
- 回滚预案
3 平滑扩容之双写方案(中小型数据)
双写方案可通过canal或mq做实现。
- 增加新库
- 数据迁移:
避免增量影响, 先断开主从,再导入(耗时较长), 同步完成并做校验
- 增量同步:
监听Canal,并开启主从同步
- 切换新库
- 修复切换异常数据(canal未同步但已切换至新库的请求), 通过定制程序读取异常日志做处理
为什么不通过MariaDB Galera集群直接扩充新的服务器节点去实现扩容?
- Galera集群是多主同步,扩充的节点提升的是并发吞吐能力,数据瓶颈问题未解决。
通过路由中间件MyCat,Sharding JDBC等, 直接扩充新的节点是否可性? - 原数据需要重新分配, 比如取模分片。
总结:
这种方案就是水平扩容,提高了并发量,但是实际大数据量的瓶颈没有解决.
4 平滑扩容之2N方案大数据量问题解决
4.1 扩容问题
项目初期,部署了数据库A及其从机A0,B及其从节点B0,为将数据平均分配,在service层,使用uid%2取模分片(可采用sharding JDBC),将数据分配到对应的数据库。如下图
随着用户量的增大,用户产生的数据量最终达到数据库的最佳存储容量,需要进行扩容,否则CRUD操作会变慢,影响服务的响应速度。
如何平滑的扩容,保证业务的连续性和高可用,对业务影响最小?
4.2 解决方案
- 先把A0和B0升级为新的主库节点,如此,由2个分库变为4个分库。同时在上层的分片配置,做好映射,规则如下:
uid%4=0
的和uid%4=2
的数据分别分配到A和A0主库中uid%4=1
的和uid%4=3
的数据分别分配到B和B0主库中
- 由于A和A0库的数据相同,B和B0库的数据相同,此时无需数据迁移,只需调整分片配置即可,可通过配置中心更新,不需要重启。
3. 扩容之后旧数据有冗余,需要对冗余数据做清理
-- 针对A,去除%4!=0的 delete from user.userinfo where uid % 4 != 0; -- 针对A0,去除%4!=2的 delete from user.userinfo where uid % 4 != 2; -- 针对B,去除%4!=1的 delete from user.userinfo where uid % 4 != 1; -- 针对B0,去除%4!=3的 delete from user.userinfo where uid % 4 != 3;
- 处理完成后,为保证数据高可用,需要再次为现有主库增加一个从库
以下为双主架构进行水平扩容,下图为现在的架构
4.3 双主架构思想
1.两台mysql都可读写,互为主备,默认只使用一台(masterA)负责数据的写入,另一台(masterB)备用;
2.masterA是masterB的主库,masterB又是masterA的主库,它们互为主从;
3.两台主库之间做高可用,可以采用keepalived等方案(使用VIP对外提供服务);
4.所有提供服务的从服务器与masterB进行主从同步(双主多从);
5.建议采用高可用策略的时候,masterA或masterB均不因宕机恢复后而抢占VIP(非抢占模式);
这样做可以在一定程度上保证主库的高可用,在一台主库down掉之后,可以在极短的时间内切换到另一台主库上(尽可能减少主库宕机对业务造成的影响),减少了主从同步给线上主库带来的压力;
但是也有几个不足的地方:
1.masterB可能会一直处于空闲状态(可以用它当从库,负责部分查询);
2.主库后面提供服务的从库要等masterB先同步完了数据后才能去masterB上去同步数据,这样可能会造成一定程度的同步延时;