零停机时间部署-过渡Db模式


14

实现零停机时间部署也涉及到同一问题,但我需要一些有关正在考虑的策略的建议。

语境

一个基于Web的应用程序,其中Apache / PHP用于服务器端处理,而MySQL DB /文件系统用于持久性。

我们目前正在建设基础设施。所有网络硬件都将具有冗余,并且所有主网络电缆都将在绑定对中使用以实现容错。服务器被配置为具有硬件容错能力的高可用性对,并且将为虚拟机容错能力和总体性能进行负载平衡。

我的目的是我们能够在不停机的情况下将更新应用到应用程序。在设计基础架构以确保可以提供100%的正常运行时间时,我付出了极大的努力。每次应用更新会有10-15分钟的停机时间,这将是非常令人失望的。这一点特别重要,因为我们打算有一个非常快速的发布周期(有时每天可能达到一个或多个发布)。

网络拓扑结构

这是网络的摘要:

                      Load Balancer
             |----------------------------|
              /       /         \       \  
             /       /           \       \ 
 | Web Server |  DB Server | Web Server |  DB Server |
 |-------------------------|-------------------------|
 |   Host-1   |   Host-2   |   Host-1   |   Host-2   |
 |-------------------------|-------------------------|
            Node A        \ /        Node B
              |            /            |
              |           / \           |
   |---------------------|   |---------------------|
           Switch 1                  Switch 2

   And onward to VRRP enabled routers and the internet

注意:DB服务器使用主-主复制

建议策略

为此,我目前正在考虑将数据库架构升级脚本分为两部分。升级如下所示:

  1. 节点A上的Web服务器脱机;流量继续由节点B上的Web服务器处理。
  2. 过渡模式更改将应用​​于数据库服务器
  3. Web服务器更新了代码库,清除了缓存,并采取了其他任何升级操作。
  4. Web服务器A联机,而Web服务器B脱机。
  5. Web服务器B代码库已更新,缓存已清除,并且已执行任何其他升级操作。
  6. Web服务器B联机。
  7. 最终模式更改将应用​​于数据库

“过渡模式”将被设计为建立跨版本兼容的数据库。这将主要利用模拟旧版本模式的表视图,而表本身将更改为新模式。这使旧版本可以正常与数据库交互。表名将包含架构版本号,以确保不会对要写入哪个表造成任何混淆。

“最终模式”将删除向后兼容性并整理模式。

简而言之,这行得通吗?

进一步来说:

  1. 是否会由于在过渡模式更改的特定点并发写入而引起问题?有没有一种方法可以确保连续执行修改表和创建向后兼容视图的查询组?也就是说,将任何其他查询保留在缓冲区中,直到完成模式更改为止,通常只有几毫秒。

  2. 有没有更简单的方法可以提供这种程度的稳定性,同时又可以在不停机的情况下进行更新?还最好避免使用“进化”方案策略,因为我不希望陷入向后方案兼容性的局限。

Answers:


4

听起来您真正想要的不是高可用性,而是您需要连续可用性

从本质上来说,您的计划将可以执行,但是您似乎已经注意到设置中的主要缺陷是,发行版中的数据库架构更改可能会导致停机或仍然可用的节点无法正常运行。连续可用性方法通过实质上创建多个生产环境来解决此问题。

生产一

该环境是用户当前正在使用的软件的实时版本。它具有自己的Web服务器,应用程序服务器以及数据库服务器和表空间。它独立于任何其他环境运行。拥有这些服务的域解析终结点的负载均衡器当前指向这些Web服务器。

生产二

这基本上是与生产版本1相同的发布登台环境。您可以在此处进行发布活动之前进行版本升级,并进行健全性测试。这也使您可以在此环境中安全地执行数据库更改。Load Balancer当前未指向该环境。

生产DR

这是位于世界不同地区的单独数据中心的另一个副本。通过在负载均衡器上进行DNS切换,可以使您在发生灾难性事件时进行故障转移。

上线

此事件实质上是将DNS记录更新为从生产一周期循环到生产二,反之亦然。这需要一段时间才能传播到世界各地的DNS服务器,因此您要使两种环境都运行一会儿。某些用户可能正在使用旧版本的软件在现有会话中工作。大多数用户将在软件的升级版本上建立新的会话。

数据迁移

唯一的缺点是,当时该窗口中并非所有用户都可以使用所有数据。以前版本的数据库中显然有重要的用户数据,现在需要安全地将其迁移到新的数据库模式中。这可以通过经过良好测试的数据导出和迁移脚本或批处理作业或类似的ETL过程来完成。

结论

一旦您完全完成了发布活动,生产二现在就是您的主要任务,并且您将开始为下一部署周期将下一个版本安装到生产一。

缺点

这是一个复杂的环境设置,需要大量的系统资源,通常需要两倍或三倍的系统资源才能成功完成。用这种方法操作可能会很昂贵,特别是如果您有非常庞大的大量使用系统。


因此,如果我理解正确,则建议您不要使用仍在使用Db的“过渡” DB模式,而应将Db-A与旧模式保持在线,而将Db-B更新为新模式。模式。当准备发布更新时,将切换Web服务器,并在准备更新时将写入Db A的数据迁移到Db B(大概是通过在特定时间标记后应用所有更改)。
Marvin

@PeterScott你明白了。请记住,在确定所有活动会话都已在旧系统中结束并且已经有足够长的时间将所有DNS缓存更新为新的CNAME或IP地址之前,您不希望运行该脚本。
maple_shaft

1
我在这两点上都应该没问题。这些会话将保留在Db中而不是服务器存储中,以避免将会话绑定到特定的虚拟机,并且我目前打算尝试使用基于非DNS的负载均衡器。我没有数据中心级别的冗余,但是可以在应用程序启动后等待一年左右。
Marvin

2

您的策略是正确的。我只想考虑将“过渡模式”扩展为一组完整的“事务表”。

对于事务表,将对标准化表执行SELECT(查询)以确保正确性。但是,所有数据库INSERT,UPDATE和DELETE总是写入非规范化事务表中。

然后,一个单独的并发流程根据已建立的业务规则和架构要求将这些更改(可能使用存储过程)应用于规范化表。

在大多数情况下,这几乎是瞬时的。但是,将动作分开可以使系统适应过多的活动和架构更新延迟。

在数据库(B)上的架构更改期间,活动数据库(A)上的数据更新将进入其事务表,并立即应用于其规范化表。

备份数据库(B)时,通过将它们写入(B)的事务表中,将对其应用(A)的事务。完成该部分后,可以放下(A)并在那里应用模式更改。(B)将完成应用来自(A)的交易,同时还处理其实时交易,该交易将像(A)一样排队,并且“实时交易”将以与(A)重新启动时相同的方式应用。

交易表行可能看起来像...

| ROWID | TRANSNR | DB | TABLE | SQL STATEMENT
    0        0       A    Name   INSERT INTO Name ...
    1        0       A    Addr   INSERT INTO Addr ...
    2        0       A    Phone  INSERT INTO Phone ...
    3        1       A    Stats   UPDATE Stats SET NrOfUsers=...

根据性能要求,事务“表”实际上可以是单独的NoSQL数据库中的行,甚至可以是顺序文件。另外一个好处是应用程序(在这种情况下为网站)的编码变得更简单,因为它仅写入事务表。

这个想法遵循与两次簿记相同的原理,并且出于类似的原因。

交易表类似于簿记“日记”。完全标准化的表类似于簿记“分类帐”,每个表都有点像簿记“帐户”。

在簿记中,每笔交易都会在日记帐中获得两个条目。一个用于“借方”分类帐帐户,另一个用于“贷方”帐户。

在RDBMS中,“日志”(事务表)为要由该事务更改的每个规范化表获取一个条目。

上表插图中的DB列指示事务在哪个数据库上发起,因此,当恢复第二个数据库时,可以过滤掉另一个数据库中排队的行,而不重新应用它们。


1
我喜欢与记账的比较。因此,据我所知,事务表允许我在将数据写入特定的规范化表时稍加延迟,以便我可以应用所有架构更改而不会在更改过程中途中断?然后,使用表的模式为最新,我可以继续将非规范化事务应用于规范化表的过程(该过程能够将旧模式数据查询映射到新模式)?
马文

1
是。您将修改映射存储过程(或其他任何方法)以容纳新旧数据。新的NOT-NULL列可能由旧数据填充,并带有表示“在用户更新时提示此提示”的代码。要拆分的列(即FULLNAME分为FIRST和LAST)将需要一些算法。我建议在表中添加1或多个“类似评论”的列,以适应新的业务需求。如果您不这样做,我保证用户会为此目的而使用其他列,那么几乎不可能修复数据。
DocSalvager '16

您如何防止将为旧模式构造的SELECT查询应用于新模式?我可以使用创建表视图并重命名架构表(具有架构版本号),但是在应用架构更改时仍然会出现问题,因为它们直接应用于规范化表。
Marvin

1
将表,列或其他任何内容添加到RDBMS时,实际上只是将行添加到只能由RDBMS引擎写入的一组内部表中。DBA通过通过VIEW查询数据库来管理数据库。由于Oracle,IBM,MS等都是专家,他们说这是最好的方法,因此我们似乎应该跟随他们。为该应用程序的每个版本创建一组VIEW。您可以在开发人员要创建的表(通常是经过相当规范化)之后对它们进行建模,以便可以适当地规范化以防止数据损坏。
DocSalvager '16

谢谢。我需要考虑一下。我在应用程序中构建一个ORM层,该层将从主域中完全删除所有状态持久性逻辑;由于更多地基于服务器端编程,因此与DB管理端相比,我倾向于从更多方面解决问题。使用我当前的策略,Db会与ORM积极管理原始表的情况保持一致。添加表视图以及可能的事务日志会增加ORM的复杂性,但同时也提供了多个架构版本的支持,而不会导致数据分裂。
Marvin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.