后端存储实战课
李玥
京东零售计算存储平台部资深架构师
立即订阅
4533 人已学习
课程目录
已完结 28 讲
0/4登录后,你可以任选4讲全文学习。
课前必读 (2讲)
开篇词 | 从今天起,换种方式学存储
免费
课前加餐 | 电商系统是如何设计的?
创业篇 (7讲)
01 | 创建和更新订单时,如何保证数据准确无误?
02 | 流量大、数据多的商品详情页系统该如何设计?
03 | 复杂而又重要的购物车系统,应该如何设计?
04 | 事务:账户余额总是对不上账,怎么办?
05 | 分布式事务:如何保证多个系统间的数据是一致的?
06 | 如何用Elasticsearch构建商品搜索系统?
07|MySQL HA:如何将“删库跑路”的损失降到最低?
高速增长篇 (7讲)
08 | 一个几乎每个系统必踩的坑儿:访问数据库超时
09 | 怎么能避免写出慢SQL?
10 | 走进黑盒:SQL是如何在数据库中执行的?
11 | MySQL如何应对高并发(一):使用缓存保护MySQL
12 | MySQL如何应对高并发(二):读写分离
13 | MySQL主从数据库同步是如何实现的?
14 | 订单数据越来越多,数据库越来越慢该怎么办?
海量数据篇 (10讲)
15 | MySQL存储海量数据的最后一招:分库分表
16 | 用Redis构建缓存集群的最佳实践有哪些?
17 | 大厂都是怎么做MySQL to Redis同步的?
18 | 分布式存储:你知道对象存储是如何保存图片文件的吗?
19 | 跨系统实时同步数据,分布式事务是唯一的解决方案吗?
20 | 如何在不停机的情况下,安全地更换数据库?
21 | 类似“点击流”这样的海量数据应该如何存储?
22 | 面对海量数据,如何才能查得更快?
23 | MySQL经常遇到的高可用、分片问题,NewSQL是如何解决的?
24 | RocksDB:不丢数据的高性能KV存储
结课测试 (1讲)
结课测试 | 后端存储,100分试卷等你来挑战
结束语 (1讲)
结束语 | 把奋斗当习惯
后端存储实战课
15
15
1.0x
00:00/00:00
登录|注册

20 | 如何在不停机的情况下,安全地更换数据库?

李玥 2020-04-11
你好,我是李玥。
随着我们的系统规模逐渐增长,总会遇到需要更换数据库的问题。我们来说几种常见的情况。
对 MySQL 做了分库分表之后,需要从原来的单实例数据库迁移到新的数据库集群上。
系统从传统部署方式向云上迁移的时候,也需要从自建的数据库迁移到云数据库上。
一些在线分析类的系统,MySQL 性能不够用的时候,就需要更换成一些专门的分析类数据库,比如说 HBase。
更换数据库这个事儿,是一个非常大的技术挑战,因为我们需要保证整个迁移过程中,既不能长时间停服,也不能丢数据。
那么,今天这节课我们就来说一下,如何在不停机的情况下,安全地迁移数据更换数据库。

如何实现不停机更换数据库?

我们都知道墨菲定律:“如果事情有变坏的可能,不管这种可能性有多小,它总会发生。”放到这里呢,也就是说,我们在更换数据库的过程中,只要有一点儿可能会出问题的地方,哪怕是出现问题的概率非常小,它总会出问题。
实际上,无论是新版本的程序,还是新的数据库,即使我们做了严格的验证测试,做了高可用方案,刚刚上线的系统,它的稳定性总是没有那么好的,需要一个磨合的过程,才能逐步达到一个稳定的状态,这是一个客观规律。这个过程中一旦出现故障,如果不能及时恢复,造成的损失往往是我们承担不起的。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《后端存储实战课》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(21)

  • 李玥 置顶
    Hi,我是李玥。

    这里回顾一下上节课的思考题:

    在我们这种数据同步架构下,如果说下游的某个同步程序或数据库出了问题,需要把 Binlog 回退到某个时间点然后重新同步,这个问题该怎么解决?

    这个问题的解决方案是这样的。如果说,下游只有一个同步程序,那直接按照时间重置Canal实例的位点就可以了。但是,如果MQ的下游有多个消费者,这个时候就不能重置Canal里的位点了,否则会影响到其它的消费者。正确的做法是,在MQ的消费订阅上按照时间重置位点,这样只影响出问题的那个订阅。所以,这种架构下,MQ中的消息,最好将保存时间设置得长一些,比如保留3天。
    2020-04-13
    7
  • hllllllllll
    在16年去o时设计的一个方案和这个很相似。需要将56亿oracle的财务数据迁移到mysql中并保证一直提供稳定的线上服务。方案主要涉及以下几点:
    1.设计同步worker以6亿/天的速度同步至mysql,预先按照1000的间隔生成560w个任务,用于保证数据同步不丢失。
    2.mysql业务数据库库为了防止和oracle中id碰撞,设计id生成器 其中,前三位为库编号;
    3.因为高达100w/分钟的事务量,设计了前置防重表+任务表(按照uuid分库),用于防重、规避热点和异步增加吞吐量;
    4.业务数据库通过在前置库生成的id分库,同时会异步同步至es;
    5.原接口服务改造,写老库数据和发送mq在一个事务(mq挂了会影响服务)。提供新接口服务写新库并发mq;
    6.接收端消费mq并根据标示同步至老库或新库;
    7.提前定义好一个阈值单号,比如当前数据已经累积到57亿,那我们可以根据增速估算一个阈值58亿。在上线后只有58亿以后的数据会通过mq同步至老库的。以前的数据都由worker同步(在适当时候:如目前单号已超过58亿,生成另外20w个任务,并开始执行另外两亿数据的同步,期间新库会缺少这两亿数据);
    8.在mq同步稳定一段时间后,用新接口灰度替代老接口,在整体稳定后全量切换至新接口,并用mq同步老库。
    2020-05-05
    13
  • Geek_80b5a9
    无知者总觉得这样做麻烦,智者满满都是细节
    2020-04-15
    11
  • 靠人品去赢
    然而我们小公司,或者比较传统的行业直接还是一个维护系统的公告,然后大晚上,凌晨加班。
    2020-04-13
    1
    6
  • 借楼请教一下李老师,无限层级(每条记录都对应一个父id)怎样设计能够快速查询,之前设计是存一个path字段,用like查询,总感觉这样设计不优雅。

    作者回复: 可以再把问题具体话一下么?我们可以一起来讨论一下。

    2020-04-11
    1
    4
  • myrfy
    不计成本的话,搭建一套全新的影子服务,在整个系统接入层做流量双写分发,切换时影子系统变为主系统,原主系统变为影子系统
    2020-04-13
    2
  • 等风来🎧
    老师,这个热切开关具体什么方式实现呢?

    作者回复: 这个一般都是通过编码来实现的。具体触发的方法,可以对外暴露一个可供调用的接口,或者通过动态配置下发等方式来触发。

    2020-05-31
    1
  • nFox
    抱歉上个留言没说说清楚,请问老师线上大表怎么在不影响业务的情况下增加字段? 我能想到的一个办法是在从库增加字段,等从库同步追上来的时候切换主从。 请问还有没有其他办法?

    另外线上扩容怎么做? 是不是和这节课更换数据库的方法一样? 加个从库,同步追上来后分库分表?

    作者回复: 大表加字段过程中会锁表,期间所有写操作都会阻塞。如果能接受的话,直接加还是最方便的。

    你提的主从切换的方式,我没有试过,理论上也是可行的。但需要特别注意切换过程中的数据一致性。

    线上扩容,相当于更换数据库,建议参照这节课中的方法操作。

    2020-05-25
  • 不忘初心
    打卡
    2020-05-23
  • nFox
    请问老师,修改线上数据库表结构怎么处理?
    我原来方案是建个新表,把旧数据倒过去,然后新旧表分别改名。
    但数据一致问题比较麻烦,改名过程中也容易出错

    作者回复: 这个问题是非常难处理的,所以,一般来说很少去删除表的字段,只增加字段。这样,新表能够兼容旧表,也就不用迁移数据了。

    2020-05-22
  • 乖,摸摸头
    数据库用的阿里云的rds , 可以用 canal 去读binlog 么,这个是不是没法弄
    2020-05-13
  • 彼得.林
    阿里的自建mysql同步到RDS,需要做些什么工作呢?是不是较检程序也是必须的

    作者回复: 这里面也要考虑实施成本VS数据重要程度来决策。

    2020-05-11
  • Jackey
    停掉双写以后,新库的数据再同步回旧库?这样就能再退回双写同时保证数据一致了吧
    2020-05-03
  • me不是一个人战斗
    对于双写阶段,会不会存在两份数据id不一致的情况(比如mysql的自增ID),如果下游有依赖这个表的ID,一旦切换就没办法回退了

    作者回复: 这种建议以一边的自增ID为准。

    2020-04-28
  • yhh
    其实比较好奇存量数据怎么从旧库同步到新库的
    2020-04-28
  • 忆澜
    有个问题,既然有比对和补偿程序,可不可以不使用数据实时同步。首先上线观察双写和补偿程序,没问题后先进行数据从旧到新的快照复制,然后开启双写,因有缝衔接而丢失的数据通过补偿程序来做……求教~

    作者回复: 考虑到很难实现一个完美的对比补偿程序,还是建议不要这么做。

    2020-04-21
  • Garwen
    思考题我理解首先要保证的是双写切换为单写新库,其次是新库挂了如何能及时回滚到旧库,且旧库的数据一直保持在最新状态。已切换意味着从新库同步binlog至旧库不可行,新库宕机后,必然出现数据丢失。那只能从业务写库方面入手。参考之前的同步方式,以及老师提示的不计成本的实现快速回滚,我猜想是不是通过缓存的方式,以及切换后全量数据放在redis中进行更新方式,此时redis中的数据没有过期时间,一旦新库出现问题,切换至旧库。此时启动更新服务,通过redis中的数据对旧库进行更新。请老师和各位同学指正。
    2020-04-12
  • Jxin
    回答:
    1.主要得解决,断开同步双写后,只写在新库的这部分数据如何同步到旧库,要严谨其实还得保证同步(这也是要用同步双写的主要原因)。讲真,水平有限,放弃同步双写后还要支持实时的同步数据真没招。那么让切换开关同时开启新库增量数据异步同步到旧库。感觉得加锁保切开关和开启增量同步两个操作原子性。严格来说还是有一会儿的停服现象(db不可用)。而且异步数据是不实时的,切回旧库还是可能因为数据未同步完,导致数据异常。比如退款一次成功了,切回来时数据更新还没做,那就还能发起一次退款申请。


    疑问:
    1.双写时,对账系统校对两个数据库数据是否一致时,要么比对一段时间内单表新增的数据行数,要么比对最新的订单是否一致。但不会去比对每一条数据是否一致。所以如果是数据更新还是可能漏了。

    2.感觉如果不停服,其实方案都很难严谨。只能做好自动校对自动补偿的系统,在切换后,尽快回复数据一致的现象。 所以午夜干稳妥。
    2020-04-11
  • leslie
    如果要不计成本那么写入时应当去追加一层数据库,按照现在主流的方式应当是redis;当我们做此操作时压力放到一头,中间件存储的最后一层减少或者降低之前的频率从而完成。
    谢谢分享,期待后续课程的更新。
    2020-04-11
  • 黄海峰
    把旧库变成新库的从库异步获取更新
    2020-04-11
收起评论
21
返回
顶部