我正在编写一个NoSQL数据库引擎,我想提供一些功能来帮助开发人员在不停止网站运行的情况下将应用程序升级到新版本,即升级期间0%的停机时间。所以我的问题是,当Web应用程序全天候运行并且经常更改其数据库结构时,Web应用程序的方法或一般设计是什么?任何例子或成功案例都将不胜感激。
答案 0 :(得分:2)
使用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"的所有用户。您可以在不影响现有站点的情况下插入较新的架构,并慢慢删除不再有用的旧架构版本。
答案 1 :(得分:2)
您将构建分布式系统。没有办法解决这个问题,因为你需要多台机器来处理重启等事情。
构建分布式系统意味着您正在做出一些选择。选择2:
您将需要负载平衡器。否则,您会遇到直接连接到您的服务的客户,由于各种原因这很粗糙。通过负载均衡器,您可以重新启动机群中的计算机,而不会导致停机。众所周知,重新启动是生活中的事实。
做你所描述的是非常艰难的。事实上,我认为对于单个开发人员而言,这几乎是一个不可能解决的问题。
使用现有的NoSQL数据库并将所有时间都花在产品上,您远远,更有可能获得更好的结果....
答案 2 :(得分:2)
如果企业可以投资数据库的地理分布。像故障转移容差;这听起来很传统,但数据复制(或数据存储区复制)不会成为路由流量的问题。
选项2: - 使用缓存(自定义开发)&循环。 例如: - 凌晨1点到凌晨2点使用数据库的快照1(假设服务器1 /数据中心1) 上午1:59 server2 / data center 2由新数据库架构(新字段,新表等)和@ 2am所有通过数据中心2的流量路由组成。
基于快照进行循环可能是需要考虑的解决方案。
答案 3 :(得分:1)
数据库结构与业务规则密切相关,因此我能想到的唯一一个数据库正在改变的场景是在项目的开发阶段。
在生产环境中,假设应用程序在业务规则方面已经稳定,因此假设数据库结构的更改很少。因此,我认为很难找到针对此案例的精心解决方案。
当然有一些天真的方法,例如在升级之前制作数据库的精确副本,将应用程序切换为在副本上运行,升级然后切换回来。
除此之外,我想不出别的什么。
答案 4 :(得分:1)
当生产环境中的许多Web服务器访问该数据库,并且您具有不兼容的代码更改(删除字段并添加新字段)时,我会建议多步骤解决方案。这有点工作,但是当一些细节出错时,你不会担心停机。
第一步扩展应用程序以便编写旧版本和新版本,部署该版本
第二步尽可能将旧数据字段值转换为新数据字段(可能需要一些时间)。
第三步将应用程序更改为只读新字段,部署
第四步删除旧字段值
第五步从代码中删除旧字段值的写入,部署它。
答案 5 :(得分:0)
唯一可能实现此目的的情况是,如果您拥有完全无状态的应用程序。无状态一词包括应用程序数据和应用程序结构。请记住,升级可能涉及更改业务对象的定义以及数据。鉴于这种无状态应用由于显而易见的原因而不实用,因此没有实际的方法来实现一般升级的零停机时间。 任何非无状态的应用程序都将具有实时用户缓存(在中间层中)业务对象定义和业务数据。升级不仅可以保证新的业务数据,还可以保证新的业务对象定义。实时用户的缓存数据总是会导致与新架构的潜在不一致。因此,除非您可以迁移中间层缓存的数据和元数据(业务定义),否则无法迁移实时用户。如果您吹掉中间层缓存,实时用户将受到影响。 您可以考虑允许实时用户继续在旧数据库下工作,并在以后将任何数据更改迁移/合并到新数据库。但这也是一个需要解决的复杂问题。 现在,可以在不影响实时用户的情况下限制零停机升级所允许的内容,或者确保在升级数据库之后,实时用户只是成为只读用户,除非他们注销并重新登录新架构。