高可用性环境中的应用程序升级



我正在编写一个NoSQL数据库引擎,我想提供一些功能来帮助开发人员在不停止网站运行的情况下将他们的应用程序升级到新版本,即在升级期间0%停机。所以我的问题是,当一个web应用程序全天候运行并且经常更改其数据库结构时,它的方法或一般设计是什么?任何例子或成功的故事将不胜感激。

使用NoSQL -特别是面向文档的数据库-您可以通过版本控制来完成此操作。

考虑MongoDB,它将所有内容存储为文档。

MongoDB允许你有一个集合(一组文档),其中每个文档的模式可以不同。

假设你有一个用户的文档:

{ "_id" : 100, "firstName" : "John", "lastName" : "Smith" }

你也可以把它作为一个文档放在同一个集合中:

{ "_id" : 123, "firstName" : "John", "lastName" : "Smith", "hasFoo" : false }

不同的模式,但都在同一个集合中。显然,这与传统的关系数据库非常不同。

解决方案是为每个具有模式版本的文档添加一个字段。然后让应用程序在每次查询时查找该版本。

MongoDB的查询可能是这样的:

users.find({ "version" : 3 }).limit(10);

返回所有使用模式版本"3"的用户。您可以在不影响现有站点的情况下插入较新的模式,并慢慢删除不再有用的旧模式版本。

您将要构建一个分布式系统。这是没有办法的,因为你需要多台机器来处理重启之类的事情。

构建分布式系统意味着你要做出一些选择。选择2个

    耐久性
  1. 强Consistancy
像S3这样的系统选择了1&2,并牺牲了3来换取"最终一致性"。你可以阅读一篇关于S3的很棒的论文。其他数据库解决方案(如DynamoDB)选择了不同的折衷方案。

你将需要负载均衡器。否则,你就会被客户直接连接到你的服务上,这是很困难的,原因有很多。负载平衡器允许您重新启动机群中的一台机器,而不会导致停机时间。重启,我们都知道,是生活的一个事实。

做你所描述的是非常困难的。事实上,我想说这几乎是一个开发者无法解决的问题。

使用现有的NoSQL数据库并将所有时间都花在产品....上,您将非常非常有可能获得更好的结果

如果一个企业可以投资地理分布的数据库。比如故障转移容忍度;这听起来很传统,但数据复制(或数据存储复制)不会成为路由流量的问题。

选项2:-使用缓存(自定义开发)&骑自行车。例如:-凌晨1点到凌晨2点使用数据库的快照1(假设是server1/数据中心1)1:59am server2/数据中心2包含新的数据库架构(新的字段,新的表等),@ 2am所有流量都通过数据中心2。

基于快照的循环可能是一个可以考虑的解决方案。

数据库结构与业务规则密切相关,因此我能想到的数据库经常更改的唯一场景是在项目的开发阶段。

在生产环境中,假定应用程序在业务规则方面已经稳定,因此假定对数据库结构的更改很少。因此,我认为很难找到详细的解决方案来解决这个问题。

当然有一些幼稚的方法,比如在升级前对数据库做一个精确的副本,切换应用程序在副本上运行,升级后再切换回来。

除了这个,我想不出别的了。

当生产环境中的许多web服务器访问该数据库时,并且您有不兼容的代码更改(删除一个字段并添加一个新字段),那么我会建议多步骤解决方案。这是一点工作,但当一些细节出错时,你不会冒停机的风险。

第一步扩展应用程序以便编写旧版本和新版本,部署该版本

第二步尽可能将旧数据字段值转换为新数据字段(可能需要一些时间)。

第三步修改应用程序为只读新字段,部署它

第四步删除旧的字段值

第五步从代码中删除旧字段值的写入,部署它

唯一可能实现这一点的情况是,如果您有一个完全无状态的应用程序。术语无状态包括应用程序数据和应用程序结构。请记住,除了数据之外,升级还可能涉及更改业务对象的定义。由于显而易见的原因,这种无状态应用程序是不实用的,因此没有实用的方法来实现一般升级的零停机时间。任何非无状态的应用程序都将有活动用户缓存(在中间层)业务对象定义和业务数据。升级可能不仅需要新的业务数据,还需要新的业务对象定义。实时用户缓存的数据总是可能导致与新模式不一致。因此,除非能够同时迁移中间层缓存的数据和元数据(业务定义),否则无法迁移实时用户。如果您删除了中间层缓存,则活动用户将受到影响。您可以考虑允许实时用户继续在旧数据库下工作,然后将任何数据更改迁移/合并到新数据库。但这也是一个很难解决的复杂问题。现在可以在不影响实时用户的情况下限制零停机升级所允许的内容,或者确保在数据库升级后,实时用户只是只读用户,除非他们注销并根据新模式重新登录。

最新更新