我正在编写一个 NoSQL 数据库引擎,我想提供一些功能来帮助开发人员将他们的应用程序升级到新版本,而无需停止网站的运行,即升级期间的 0% 停机时间。所以我的问题是,当 Web 应用程序 24/7 运行并且经常更改其数据库结构时,它的方法或一般设计是什么?任何示例或成功案例将不胜感激。
6 回答
使用 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 点到凌晨 2 点使用数据库的快照 1(假设服务器 1/数据中心 1)凌晨 1 点 59 分服务器 2/数据中心 2 由新的数据库架构(新字段、新表等)和 @ 凌晨 2 点所有流量路由通过数据中心 2。
循环基于快照可能是一个需要考虑的解决方案。
你将要构建一个分布式系统。没有办法解决这个问题,因为您需要多台机器来处理重启等事情。
构建分布式系统意味着您正在做出一些选择。选择 2:
- 耐用性
- 可用性
- 强一致性
像 S3 这样的系统选择了 1 和 2,并通过牺牲 #3 来支持“最终一致性”而付出了代价。您可以阅读一篇关于 S3的好论文。其他数据库解决方案,如 DynamoDB,选择了不同的权衡取舍。
您将需要负载平衡器。否则,您会遇到直接连接到您的服务的客户,这很困难,原因有很多。负载均衡器可让您重新启动队列中的机器,而不会导致停机。众所周知,重启是生活中的事实。
做你所描述的事情是非常艰难的。事实上,我想说这对于单个开发人员来说几乎是一个不可能解决的问题。
使用现有的 NoSQL 数据库并将所有时间都花在产品上,您获得更好结果的可能性要大得多……
当生产环境中的许多网络服务器访问该数据库时,您的代码更改不兼容(删除了一个字段并添加了一个新字段),那么我建议采用多步骤解决方案。这是一项工作,但当某些细节出现问题时,您不会冒停机时间的风险。
第一步扩展应用程序,以便编写新旧版本,部署该版本
第二步尽可能将旧数据字段值转换为新数据字段(可能需要一些时间)。
第三步将应用程序更改为只读新字段,部署它
第四步删除旧的字段值
第五步从代码中删除旧字段值的写入,部署它。
数据库结构与业务规则息息相关,所以我能想到的数据库经常变化的场景只有在项目的开发阶段。
在生产环境中,假设应用程序在业务规则方面已经稳定,因此假设数据库结构的更改很少。因此,我认为很难为这种情况找到详尽的解决方案。
当然还有一些幼稚的方法,例如在升级之前制作数据库的精确副本,切换应用程序以在副本上运行,升级然后切换回来。
除此之外,我想不出别的了。
The only possible case where this can be achieved is if you have a completely stateless application. The term stateless includes both application data and application structure. Remember the upgrade may involve changing the definition of the business objects in addition to data. Given that such stateless application is not practical due to obvious reasons, there is no practical way to achieve zero downtime for general upgrades. Any application that is not stateless will have the live users caching (in the mid-tier) business object definitions and business data. An upgrade may warrant not only new business data but new business object definitions. The cached data by live users can always cause potential inconsistencies with the new schema. So live users can not be migrated unless you can migrate both the data and meta data (business definitions) cached in the mid-tier. If you blow away the mid-tier cache, the live users will get affected. You may consider allowing live users to continue working under the old db and migrating/ merging any data changes to the new db later. But that is a complicated problem to solve as well. Now it is possible to restrict what is allowed under a zero downtime upgrade without affecting live users or make sure that after the database is upgraded, the live users just become read-only users unless they log out and log back in against the new schema.