MySQL 读写分离、分库分表、归档、不停服数据迁移

1、缓存和数据库方案的选择:是否与用户有关?

缓存:电商商品系统,搜索等、任意用户访问内容都一样

数据库:订单系统、账户系统、购物车系统


2、MySQL应对高并发读写方案

读写分离:增加更多副本,提供读流量的均摊

分片:业务维度拆分到不同机器DB

分库分表:同业务流量穿透到不同机器DB  =》 数据量大则分表,并发高就分库

 

3、读写分离技术

 

 

A: 读写请求组件方案

纯手工:根据读写指定不同数据源

组件方式:Sharding-JDBC,组件集成应用程序,自动请求路由到数据库实例  =》 优点:无需关注分库分表逻辑;缺点:各个系统都需要配置路由规则

代理方式:应用层和数据库层增加一组数据库代理实例,例如MyCat,Atlas,MaxScale等; =》缺点:中间件稳定性和流量多一层穿透

 

B: 配置多个从库的HA方案

HAProxy+Keepalived 

 

C: 读写分离数据不一致性解决

主从同步延迟正常<1ms,非核心服务使用该模式

方案一:前端体验优化   =》操作完成展示广告信息或完成信息,再给用户查询

方案二:核心服务采用主DB =》 更新数据库和查询放入同一事务,规避主从不一致问题

 
4、分库分表技术
原则:能不拆就不拆、能少拆不多拆;
a、数据量大,就分表 =》解决查询慢,只要减少每次查询的数据总量即可 (限制搜索时间范围,限制子查询数量,限制join双方数据量)
b、并发高,就分库 =》并发请求均摊到不同数据库实例
 
分片Sharding Key选择
按照范围分片 =》 容易产生热点问题
方法1:采用更均匀的Hash算法
方法2:查表法,分片算法随时可以改动;如果发现某个分片是热点数据,则可以将这个分片再拆成多个分片

 

5、归档技术

 

 

 

批量删除
1
2
select max(id) from orderswhere timestamp < SUBDATE(CURDATE(),INTERVAL 3 month);
delete from orderswhere id <= ?order by id limit 1000;

 问题:历史单删除后,MySQL磁盘空间并没有减少?产生碎片,利用率低;

原因:每个表是B+数,物理上每条记录存放在磁盘文件中,这些记录通过一些位置指针构成一棵B+树;删除记录时候,只是将B+树中相关指针完成删除。

1
2
3
4
5
6
7
8
-- 新建一个临时订单表
create table orders_temp like orders;
-- 把当前订单复制到临时订单表中  大于3个月前的数据
insert into orders_temp select * from orders where timestamp >= SUBDATE(CURDATE(),INTERVAL 3 month);
-- 修改替换表名
rename table orders to orders_to_be_droppd, orders_temp to orders;
-- 删除旧表
drop table orders_to_be_dropp

 

 6、不停服数据迁移技术 (双写、切读、切写)
 
原则
1、每步可逆:保证执行每步骤后,一旦出现问题,能快速回滚到上一个步骤
2、最小化迁移:历史数据提前迁移
 
DAO层改动
1、支持双写新旧库:预留切换开关,通过开关控制三种写状态(只写旧库,只写新库和同步双写)
2、支持双读新旧库:预留热切换开关,控制读旧库和新库
 
步骤
1、上线同步程序,从旧库中复制数据到新库中,并实时保持同步;   =》 目的保证新数据量一致
        方案1:取业务主键,自增列
        方案2:使用Binlog实时同步数据,如果不是Mysql,可以采用复制状态机理论实现(快照+日志)技术;
                    风险 =》影响线上性能,停掉即可
      
   
2、上线双写订单服务,只读写旧库;  
      要求:运行1到2周,验证新版订单服务的稳性和新旧库数据是否一致。
      可逆:新版服务有问题,立即下线新版服务,回滚旧版服务
     
3、开启双写,同时停止同步程序;
       要求:停止同步程序;先写旧库,再写新库;
       双写策略
              旧库写成功,新库写失败,返回成功;记载日志,后续用日志验证新库是否有问题
              旧库写失败,直接返回失败,不再写新库;不能让新库影响现有业务的可用性和数据准确性
       可逆:上面过程出现问题,关闭双写开关,回滚到只读写旧库状态
 
4、开启对比和补偿程序,确保新旧数据库数据完全一样; =》 验证数据准确性一致
       切换到双写后,新库和旧库数据存在不一致的情况
       a、停止同步程序和开启双写,很难做到无缝衔接
       b、双写策略不保证新旧库数据强一致
     
       比对补偿程序:比对旧库最近的数据变更,检查新库数据是否一致,如果不一致,需进行补偿

      

         要求:稳定运行几周时间,不断检查,确保不能有旧库写成功,新库写失败情况出现。 对比程序不能出现新旧两个库数据不一致的情况

         难点:比对两个随时变换的数据库中的数据,没有类似复制状态机理论。

              不变数据(订单数据)
                比对:根据订单完成时间,每次比对时间窗口内完成的订单 (完成时间+MD5值)
                补偿:发现不一致,使用旧库更新新库
             
              易变数据(商品信息数据)
                比对:取旧库更新时间窗口内的数据,取新库找相同主键数据进行比对,比对数据和更新时间是否一致;如果不一致(Vnew <V old),暂不补偿,到下个时间窗口继续比对。时间窗口的结束时间,不取当前时间(避免数据正在写入),取当前时间-1分钟的时间。
                补偿:下个时间窗口补偿              
 
5、逐步切量读请求到新库上;
         要求:灰度发布,将流量一步步迁移到新库。
         可逆:出现问题,切回旧库。
   
6、下线对比补偿程序,关闭双写,读写都切换到新库上;
         这步骤不可逆,这个过程主要是摘掉旧库
 
7、下线旧库和订单服务的双写功能
           
 
 
posted @   mick0802  阅读(1533)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
点击右上角即可分享
微信分享提示