V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
KentY
V2EX  ›  程序员

关于应用程序的 Deployment 与 Database Changes, 诸位在实际中是如何处理的?

  •  
  •   KentY ·
    sk1418 · 2020-01-23 22:27:41 +08:00 · 2651 次点击
    这是一个创建于 1526 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我当前的一个 Project 中囊括大概一百有余 apps, 70-80%为 Java/kotlin apps,所有这些是借由 flyway 来管理每次 release 的 database changes. 所有 applications 可能与不同的 database 连接, 在 app 启动的时候检查并执行 flyway 脚本.

    通常情景下, 此方案尚可行, 且所有同事也已熟知 flyway 的优缺点, 这个方案也成为了 Project 里的一个"传统".

    然而, 有一些情况, 采取这个方式就显得比较棘手. 比如, 在 database 的修改中, 有一些语句需要 1-2 小时的时间执行. 例如, 重建 index 或者新建一些无 default 的 col. 如果仍然依仗 flyway 来处理这些语句, 那么 deployment 以后, app 的启动时间将会 1-2 小时之久. 这是不能接受的一个情况. 所以现在对这种情况只有在开发的时候, 发现有这种可能的语句, 不放在 flyway 脚本中, 而是单独出来, 放在一个地方, 然后弄一个 ticket (we are using JIRA heavily), 在需要 release 的时候人工来执行这些语句, 之后再进行 app 的 deployment.

    还有一个问题就是, database changes 包含 rename, del column 这种, 就会更加麻烦. 目前我们是尽量避免这种操作, 如果确实需要, 就只 add new, 然后等下一次 deployment 之日, 再进行 delete 操作. 因为我们采用 rolling deployment, 当前的 deployment 如果失败,比如有错误或者超时, 不会影响现在正在运行的 pods (我们使用 openshift) . 但是如果有 database 结构的删除操作, 当前运行的 pod 就会不正常.这个也是不能接受的. 我们要尽量实现用户角度不察觉的 release.

    我觉得当前采取的各种措施都不是自动化的, 很多人工参与因素. 应该不是最优的. 我能想到的稍微(可能)好一些的方案是 2 个数据库的热切换, deployment 在 A, running pod 在 B, 然后数据再同步. 可是这个对于我们现在是不可行的, 因为数据量确实大, 没办法双份热切换.

    不知道各位有没有类似的问题, 是如何处理的. 特别是有 database 结构删除操作和较为耗时的数据库语句的情况.

    先行感谢.
    16 条回复    2020-01-25 15:28:33 +08:00
    tomczhen
        1
    tomczhen  
       2020-01-23 23:33:40 +08:00 via Android
    让我想起之前的求职的时候,对方应该是开发负责人。他似乎觉得 online DDL 有简单的通用方案解决所有问题。我只能说用 schemaless 数据库会好受一些。

    你的感觉方向是对的,不过实践嘛,我只看过几个大厂的技术方案分享就觉得真的太多坑了。说到底,如果 online DDL 的代价超过停机的代价,还是停机吧。。。
    monsterxx03
        2
    monsterxx03  
       2020-01-23 23:55:56 +08:00 via iPhone
    大同小异,我们 db migration 的工具是自己写的,但也没什么特别的,也是生成下 sql 然后执行。

    实际上线的时候,如果有 schema change, 会分两次 deploy,第一次部署到单独的 server(日常主要是跑 cron,和一些手工脚本的,不承担用户流量),在上面手工运行,用的 mysql(<8.0)原生的 online ddl,但这个也需要在流量低谷时候执行,io 开销很大。同时要求 schema change 做到兼容,第二次部署再把用到新 schema 结构的代码 rollout 到所有 server。整个过程没有 down time,但比较繁琐。

    pt schema change 和 github 开源的那个工具原理也大同小异,好处是可以看到进度和控制速度,但和现有流程集成更麻烦点,没有在用。

    完全自动化也不是不可能,但也要和线上流量做 trade off,对业务规模来说,得不偿失。业务要完全设计成 schemaless 也不太现实。
    KentY
        3
    KentY  
    OP
       2020-01-24 06:13:18 +08:00
    @monsterxx03 我们的项目里, 大概有 3,40 个 apps 是客户直接用的, 也就是说对人的, 剩下大部分都不是对人的. 而且几乎没有流量低谷的时候, 各个时区都会有来往数据, 其中一些吞吐量还挺大. 每次产生未预计的 out-age 或者 downtime 都算是大事故, 因为各个 apps 之间都有通信.
    虽然现在手工干预也可以凑合, 但是隐患挺多. 整个项目一共 100 多个开发人员, 并不是所有都对 database 的变动后果很了解, 也许在自己开发环境, 几毫秒就过去的几句语句, 到了 production stage 会产生意外的效果. 我们只有几个 database experts, 如果休假, 或者病假等, 也是问题, 而且直接手工操作 database 总觉得是有些不保险. 常有 squads 反应此类问题. db changes 和 deployment 这个问题一直也没有比较好的解决方法. 所以来问问.
    wd
        4
    wd  
       2020-01-24 06:43:00 +08:00 via iPhone
    没用过 flyway。数据库变更应该和 app 是无关的,每次 release 先做数据库变更,再 release app。数据库变更的 sql 必须要交给专业人士审核执行,至少做到变更对现在运行的 app 没影响。
    KentY
        5
    KentY  
    OP
       2020-01-24 07:55:58 +08:00
    @wd "数据库变更应该和 app 是无关的" it depends... 如果你看了我问题的内容, 就不难设想, 如若我 delete 一个 column, 那么当前运行的 app 就自然会有影响. 所以你说的"每次 release 先做数据库变更,再 release app" 就不成立. 这也是我们现在尽可能避免(原则上禁止)做结构删除 /renaming 的变更. 但这不是问题的 solution.
    wd
        6
    wd  
       2020-01-24 08:10:03 +08:00 via iPhone
    @KentY #5 这就是 solution 我们就是这么做的,你认为不是可以继续找找。
    momocraft
        7
    momocraft  
       2020-01-24 10:13:50 +08:00
    感谢分享。我们也用 flyway (和 scala 一起)。index 和 schema change 的做法和你说的类似。

    也许 有 fs/volume snapshot 配合可以做到你说的那种热切换 (我没有试过) ?

    可能 schema 现在是数据库中比较不分布式友好的部分了
    KentY
        8
    KentY  
    OP
       2020-01-24 16:30:59 +08:00
    @wd 对不起, 可能我在以上之回复中没说明白, 让你误解了. 我想表达的是我们现在所做的对于我们面临的问题来说, 不是 solution.
    wd
        9
    wd  
       2020-01-24 16:36:24 +08:00 via iPhone
    @KentY #8 有点不明白你要的 solution 是啥?就是一定要满足可以在启动 app 的时候执行数据库变更么?你说的切换数据库也会有丢失数据的可能。
    KentY
        10
    KentY  
    OP
       2020-01-24 16:53:53 +08:00
    @momocraft 感谢你的经验分享. 我们也有不多的 scala 应用. 大概 3-5 个. 还有一部分 python 的数据分析 apps.
    我们的大体数据库存储结构是, 主要数据库是微软公司的 azure, 然后部分 apps 都 etl 到自己的 postgres, 我说的问题对于这些访问 postgres 的应用来说并不困难, 我写了相关的脚本, 基于 postgres 的应用目前可以 deploy 到跟 running pods 不同的 database schema. 因为 etl 的数据可以随时重新刷一遍, 只是时间问题, 然后再在 openshift 中切换 pod,or configuration 即可

    但是如果是与根源 azure 数据库打交道的应用程序, 就面临我上面的挑战了.

    题外话, 我们大部分 database experts 都是具备很强的 oracle 背景的, 在实际使用中, 他们常常对于 azure 嗤之以鼻. :-D
    KentY
        11
    KentY  
    OP
       2020-01-24 17:07:21 +08:00
    @wd 这个问题的描述我觉得还是说清了... 看来我的表达能力还是不尽如人意.
    简单再说一下, 希望能表述更明白.
    我们的 app 启动是有 timeout 的通常是 2-5min.超出了的话, 会有 alert, 这些管理不由开发团队负责, 甚至是另一个公司来监控, 每次这种都是要付费. 因为保险安全缘故,我们不能把 timeout 设置成比如 2 小时, 3 小时, 这样有时候会隐藏真正的问题. 所以数据库变更语句执行的时间如果较长, 我们会有问题.这是问题 1.

    问题 2, 如果有 table 结构 rename, delete, 按你分享的, database changes 跟 deployment 分离对于我们就不一定适合. 因为先行手工执行了 db changes, 这个时候, 还在运行的 apps 就会出问题, rolling deployment 就被打破了. 就有了 outage..

    对于问题 2, 不一定非要在 app 启动时做 database change, 任何时候都可以. 但是要求当前运行在同一 database 的所有 apps 到新的版本 deployment 结束并切换之前继续正常运行, 因为新版本不论是 deployment 还是 starting up 一旦有问题, 不能影响当前产品提供服务. 大概这个问题的困难也是在这里.
    KentY
        12
    KentY  
    OP
       2020-01-24 17:16:04 +08:00
    @wd 补充一下, 当前我们采取的措施前面已经说了, 可以勉强应付, 但是人为手工干预因素比较多, 而且需要特定人直接在数据库上进行操作. 这些严格讲不符合安全规范, 因为开发团队不能直接操纵 production stage 的数据. 另外一个人工干预也会有出错的潜在可能, 以及具体人员的依赖性.
    所以我说现在的做法虽然能将就, 但我感觉不是 solution.
    UnknownR
        13
    UnknownR  
       2020-01-24 17:30:05 +08:00
    我们这是复制了完整的测试环境,先在 test 跑,没问题了上 prod,再有问题就 rollback,确保没有明面上的问题。隐藏问题靠砸钱,database 1 主 3 备加 3 个数据中心,有问题了就切。开发和部署权限分离,加 2 个团队,开发本地测完再推给部署,部署的再上 test,都没问题了再上 prod 的主 dc,跑下来没问题就最后部署备份的 dc,如果主 dc 出问题了,备份 dc 还没做 change,切过去还能继续跑
    wd
        14
    wd  
       2020-01-24 18:05:55 +08:00
    @KentY 我看了一下好像我说的方法你也想到了的。所以问题可能是你想让这个过程变成自动的,不需要人工参与?

    我们的使用场景里面,有测试运维开发,开发只对开发环境有操作权限( db,服务器),测试只对测试环境有操作权限,运维对线上有权限。开发想要发布,先经过测试测试,测试完毕之后会提交给运维发布。不知道你们是不是也有这几个角色?我觉得分角色是安全的。

    这样发布的时候,不管是代码发布,还是数据库变更,都是有专业人员做的。他们会再次 review 发布过程。这样就是按照我说的流程,先发布数据库变更(会保证数据库变更不会影响现有程序),然后发布程序代码。这样没有停机时间。但是这样确实是会导致不能兼容现有正在运行的程序的事情不能做,比如删除字段。

    另外这里面也只是多个角色的人参与进来 review 代码,发布过程可以通过点一个按钮什么的自动执行,不知道是否不符合你说的人工参与太多。审计的理念应该是多角色参与互相审核会是一个比较安全的操作。
    KentY
        15
    KentY  
    OP
       2020-01-24 18:26:11 +08:00
    @UnknownR 我们也有不同 stages, 有 fallback database, 但是这个不参与平时正常的运行, 只有正常的出问题了, 才会切过去, 而且数据不是实时同步的.
    一般能到 production deployment 的阶段都是经过了测试的, 我们有 dev, test and prod three stages.
    @wd
    我们没有专门的部门 /团队负责 release. 正如我前面所讲, 我们有 100 多个 apps, 但是项目会按照业务的不同, 分为多个 squads, 比如咱们的 squad 负责某项业务, 提供了 1-10, 10 个 apps. 那么咱们这个小团队就要负责开发, 测试,以及咱们自己 apps 的 release. 至于 release 的周期也是咱们自己决定. 我们不可能有一个专门的团队负责所有 release. 大部分 squads 采用 scrum, kanban or "scrumban"来开发, release 可能随时要求, 也可能集中要求, 各个 apps 的 release 需求还不同, 让一个专门团队负责 release 有点困难. 我们只有一些重要的 apps 在 prod stage 运行期间, 由另一个公司负责监控, 但相关的 squad 是可以直接 prod release 的.
    ps1aniuge
        16
    ps1aniuge  
       2020-01-25 15:28:33 +08:00
    会有 alert, 这些管理不由开发团队负责, 甚至是另一个公司来监控, 每次这种都是要付费. ----------请允许我插播广告,解决这个问题。
    《卡死你 3000 》,开源免费的批量运维工具。https://gitee.com/chuanjiao10/kasini3000
    欢迎了解下。
    这个软件近期( 10 天内)将更新,新增任务计划功能。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1805 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 16:29 · PVG 00:29 · LAX 09:29 · JFK 12:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.