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、下线旧库和订单服务的双写功能
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)