2013-05-04 72 views
11

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

+0

出于兴趣,为什么你写的NoSQL数据库引擎?现有的产品是否适合您的需求? – hertzsprung 2013-05-12 19:03:39

+0

请注意,只有在取走一个字段时才添加字段没有任何伤害... – 2013-05-13 23:01:51

+0

所有数据库都很慢。我写一个非常快速的发动机将在约2000个时钟周期做一个INSERT,这将是每秒2000万左右的INSERT语句中的平均笔记本电脑 – Nulik 2013-05-19 02:16:14

回答

1

数据库结构与业务规则密切相关,因此数据库经常变化的唯一场景就是处于项目的开发阶段。

在生产环境中,假定应用程序在业务规则方面已经稳定,因此假定对数据库结构的更改很少。因此,我认为要为这种情况找到详尽的解决方案将非常困难。

当然,天真的方法就像在升级之前制作数据库的精确副本,将应用程序切换到副本上运行,升级然后切换回来。

除此之外,我想不出别的。

+0

可以说,例如,移动电话已经过时,没有人使用它了,取而代之的是我们思想沟通。 Facebook现在需要删除手机号码,并添加一个名为“思想摘要”的新字段,这将允许您传达加密的想法。当每秒有100万个请求时,如何在几秒钟内升级Facebook?关于prod和dev环境我们已经知道的东西 – Nulik 2013-05-05 13:02:33

+0

Facebook是一个分布式系统。这完全是另一回事。 – 2013-05-05 14:31:52

+0

加上你的场景不是“经常改变它的数据库结构” – 2013-05-05 14:33:34

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” 的所有用户。您可以在不影响现有站点的情况下插入较新的模式,并慢慢删除不再有用的旧模式版本。

2

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

构建分布式系统意味着您正在做出一些选择。挑的2:

  1. 耐久性
  2. 状况
  3. 斯特朗相合

系统像S3,选择1 & 2和通过有利于 “ - 最终相合” 的牺牲#3支付的价格。有一个great paper on S3你可以阅读。其他数据库解决方案(如DynamoDB)选择了不同的折衷方案。

您将需要负载平衡器。否则,你会被直接连接到你的服务的客户卡住,这是由于各种原因的粗糙。负载平衡器可让您重启机群中的机器,而不会导致停机时间。众所周知,重新启动是生活中的事实。

做你所描述的是非常艰难的。事实上,我认为单个开发人员解决这个问题几乎是不可能的。

你是很远很远,更可能使用现有的NoSQL数据库,并花所有的时间对你的产品合作,以获得更好的结果....

2

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

选项2: - 使用缓存(定制开发)&循环。 (例如,server1/data center 1) 1:59 am server2/data center 2由新的数据库架构(新的字段,新的表格等)和@ 2am所有通过数据中心2的交通路线。基于快照的自行车骑行可能是一个需要考虑的解决方案。

1

当许多网络服务器在生产环境中访问该数据库,和你有一个不兼容的代码更改(删除字段,并增加了一个新的领域),那么我会建议多步骤的解决方案。这是一个有点工作,但是当某些细节出错时,你不会提前停机。

第一步,使旧的和新的版本被写入扩展应用,部署版本

第二步转换尽可能旧的数据字段值到新的数据字段(可能花点时间)。

第三步更改应用程序仅读取新的领域,它部署

第四步删除旧的字段值

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

0

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