是否存在防灾语言?

时间:2009-09-10 07:53:55

标签: programming-languages language-design

在创建必须具有高可靠性的系统服务时,我经常最终编写了许多“故障保护”机制,以防万一:通信已经消失(例如与DB通信),如果发生了什么,电源丢失,服务重新启动....如何拿起碎片并以正确的方式继续(并记住拾取碎片时电源可能会再次出现......)等等

我可以想象,对于不太复杂的系统,一种能满足这一要求的语言非常实用。所以这种语言在任何特定时刻都会记住它的状态,无论电源是否被切断,还是从中断的地方继续。

这是否存在?如果是这样,我在哪里可以找到它?如果没有,为什么不能实现呢?在我看来,关键系统非常方便。

P.S。如果数据库连接丢失,则表示出现问题,需要手动干预。在他恢复连接的那一刻,它会在它停止的地方继续。

编辑: 由于讨论似乎已经过时了,所以让我补充几点(在我可以为问题添加赏金之前等待)

Erlang的回应现在似乎是最受欢迎的。我知道Erlang并且读过Armstrong(主要创作者)的实用书。这一切都非常好(虽然函数式语言使我的头部旋转所有递归),但“容错”位不会自动出现。离得很远。 Erlang提供了许多监督程序和其他方法来监督进程,并在必要时重新启动它。但是,要正确地制作适合这些结构的东西,你需要成为erlang大师,并且需要让你的软件适合所有这些框架。此外,如果电源掉电,程序员也必须拿起碎片并尝试在下次程序重启时恢复

我正在寻找的东西更简单:

想象一种语言(例如,像PHP一样简单),您可以执行诸如数据库查询,操作,执行文件操作,执行文件夹操作等操作。

它的主要特征应该是:如果电源耗尽,并且事情重新启动它就会从它停止的地方开始(因此它不仅会记住它的位置,它还会记住变量状态)。此外,如果它在文件复制过程中停止,它也将正确恢复。等等。

最后但并非最不重要的一点是,如果数据库连接断开且无法恢复,语言就会暂停,并发出信号(可能是系统日志)进行人为干预,然后继续进行中断。

这样的语言会使很多服务编程变得更容易。

编辑: 似乎(根据所有评论和答案判断)这样的系统不存在。并且可能不会在近乎可预见的将来由于它(接近?)不可能做到正确。

太糟糕....再次我不是在寻找这种语言(或框架)让我登上月球,或用它来监视某人的心跳。但对于小型定期服务/任务总是有大量的代码处理边框(在中间的某个地方断电,连接丢失而不是恢复),...这里暂停,...修复问题,... ..并继续你离开的地方方法会很好。

(或作为评论者指出的检查点方法(如在视频游戏中)。设置检查点....如果程序死亡,请在下次重新启动。)

赏金奖励: 在每个人都得出结论的最后一分钟,它无法完成,Stephen C带有napier88,它似乎具有我正在寻找的属性。 虽然它是一种实验性语言,但它确实可以证明它可以完成,而且值得研究更多。

我将考虑创建自己的框架(可能使用持久状态和快照)来添加我在.Net或其他VM中寻找的功能。

每个人都感谢您的投入和深刻的见解。

28 个答案:

答案 0 :(得分:59)

答案 1 :(得分:33)

Software Transactional Memory (STM)与非易失性RAM相结合可能会满足OP修订后的问题。

STM是用于实现“事务”的技术,例如,作为原子操作有效地完成或根本不完成的动作集。通常,STM的目的是使高度并行的程序能够以比传统的锁定资源编程更容易理解的方式在共享资源上进行交互,并且由于具有高度乐观的无锁定风格而可以降低开销。节目。

基本思想很简单:记录“事务”块内的所有读写(以某种方式!);如果任何两个线程在其任一事务结束时在这些集合上发生冲突(读写或写 - 写冲突),则一个被选为胜利者并继续,另一个被迫将其状态回滚到开头交易并重新执行。

如果坚持所有计算都是事务,并且每个事务的开头(/ end)的状态存储在非易失性RAM(NVRAM)中,则可以将电源故障视为事务故障,从而导致“回滚” 。计算只能以可靠的方式从交易状态进行。这些天的NVRAM可以用闪存或电池备份来实现。人们可能需要很多NVRAM,因为程序有很多状态(最后看小型机的故事)。或者,可以将已提交的状态更改写入写入磁盘的日志文件;这是大多数数据库和可靠文件系统使用的标准方法。

STM目前的问题是,跟踪潜在的交易冲突有多贵?如果实施STM会使机器速度下降很多,那么人们将会接受现有的略微不可靠的方案而不是放弃这种性能。到目前为止,这个故事并不好,但研究还很早。

人们通常没有为STM设计语言;出于研究目的,他们主要是 使用STM增强Java(参见今年6月的ACM通讯文章)。我听说MS有一个C#的实验版本。英特尔有一个C和C ++的实验版本。 维基百科页面有很长的列表。和功能编程人员 像往常一样,声称功能程序的无副作用属性使STM在函数式语言中实现起来相对微不足道。

如果我没记错的话,早在70年代,在分布式操作系统中就有相当多的早期工作,其中进程(代码+状态)可以在一台机器之间轻而易举地运行。我相信几个这样的系统明确允许节点故障,并且可以从另一节点中的保存状态重启故障节点中的进程。早期的关键工作是在 Dave Farber Distributed Computing System。因为在70年代设计语言很受欢迎,我记得DCS有它自己的编程语言,但我不记得名字。如果DCS不允许节点故障并重新启动,我相当确定研究系统的后续工作。

编辑:1996年的系统,乍一看似乎有你想要的属性 记录here。 它的原子事务概念与STM背后的思想是一致的。 (去证明太阳下没有太多新东西。)

旁注:70年代回归,核心记忆仍然是王道。核心是磁性的,在电源故障时是非易失性的,许多小型计算机(我相信大型机)都有电源故障中断,在电源断电前几毫秒通知软件。使用它,可以轻松存储机器的寄存器状态并完全关闭。当电源恢复时,控制将返回状态恢复点,软件可以继续。因此,许多程序可以在电源闪烁和可靠重启后继续存在。我亲自在Data General Nova小型机上建立了分时系统;你实际上可以让它运行16个远程类型的全面爆炸,接通电源,并重新启动并重新启动所有的电传类型,好像什么都没发生一样。从嘈杂到沉默和背部的变化令人惊叹,我知道,我不得不多次重复调试电源故障管理代码,它当然做了很棒的演示(插上插头,扼杀沉默,插回...... )。这样做的语言的名称当然是汇编程序: - }

答案 2 :(得分:13)

我怀疑你所描述的语言特征是否有可能实现。

原因在于,定义常见和一般故障模式以及如何从中恢复将非常困难。考虑一下您的示例应用程序 - 一些具有一些逻辑和数据库访问权限的网站。并且假设我们有一种语言可以检测电源关闭和后续重启,并以某种方式从中恢复。问题是,不可能知道语言如何恢复。

假设您的应用是在线博客应用。在那种情况下,从我们失败的那一点开始就足够了,一切都好。但是,请考虑网上银行的类似情况。突然间,从同一点继续下去已经不再聪明了。例如,如果我试图从我的帐户中提取一些钱,并且计算机在检查之后但在执行提款之前就已经死了,然后一周之后它就会回来,即使我的帐户在现在消极。

换句话说,没有一个正确的恢复策略,所以这不是可以在语言中实现的东西。什么语言可以告诉你什么时候发生了不好的事情 - 但大多数语言已经支持异常处理机制。其余的由应用程序设计人员来考虑。

有许多技术可以设计容错应用程序。数据库事务,持久消息队列,群集,硬件热交换等等。但这一切都取决于具体要求以及最终用户愿意支付多少费用。

答案 3 :(得分:13)

据我所知,Ada经常用于安全关键(故障安全)系统。

  

Ada最初的目标是   嵌入式和实时系统。

     

Ada的显着特征包括:   强大的打字,模块化机制   (包),运行时检查,   并行处理(任务),异常   处理和泛型。 Ada 95补充道   支持面向对象   编程,包括动态   调度。

     

Ada按顺序支持运行时检查   以防止访问   未分配的内存,缓冲区溢出   错误,逐个错误,数组   访问错误,以及其他可检测的   错误。可以禁用这些检查   运行效率的兴趣,   但通常可以有效地编译。   它还包括帮助设施   程序验证。

     

对于这些   原因,阿达被广泛使用   关键系统,任何异常   可能导致非常严重   后果,即意外死亡   或受伤。系统的例子在哪里   Ada用于航空电子,武器   系统(包括热核   武器)和航天器。

N-Version programming也可能会给你一些有用的背景阅读。

¹基本上是一位熟悉嵌入式安全关键软件的人

答案 4 :(得分:11)

有一种称为Napier88的实验性语言(理论上)具有防灾的一些属性。该语言支持正交持久性,并且在一些实现中,这扩展(扩展)以包括整个计算的状态。具体来说,当Napier88运行时系统将正在运行的应用程序检查指向持久性存储时,当前线程状态将包含在检查点中。如果应用程序崩溃并以正确的方式重新启动它,您可以从检查点恢复计算。

不幸的是,在这种技术准备好主流使用之前,需要解决许多难题。这些包括确定如何在正交持久性的上下文中支持多线程,确定如何允许多个进程共享持久存储,以及持久存储的可伸缩垃圾收集。

存在使用主流语言进行正交持久化的问题。已经尝试过用Java做OP,包括由Sun(Pjama项目)相关人员完成的,但目前没有任何活跃的。如今,JDO / Hibernate方法更受青睐。


我应该指出,正交持久性在很大程度上并不是真正的防灾。例如,它无法处理:

  • 重启后与“外部”系统重新建立连接等,
  • 导致持久数据损坏的应用程序错误,或
  • 由于检查点之间的系统崩溃而造成的数据丢失。

对于那些人,我不相信有一些可行的通用解决方案。

答案 5 :(得分:10)

大多数此类努力 - 称为“fault tolerance” - 都围绕着硬件,而不是软件。

最极端的例子是Tandem,其“不间断”机器具有完全冗余。

在硬件级别实现容错是有吸引力的,因为软件堆栈通常由来自不同提供商的组件构成 - 您的高可用性软件应用程序可能会安装在操作系统之上的一些明显不稳定的其他应用程序和服务上。是片状的,并使用明显易碎的硬件设备驱动程序..

但在语言层面,几乎所有语言都提供了正确错误检查的工具。但是,即使使用RAII,异常,约束和事务,这些代码路径也很少被正确测试,很少在多故障场景中一起测试,并且通常在错误处理代码中隐藏错误。所以更多的是关于程序员的理解,纪律和权衡,而不是语言本身。

这使我们回到硬件级别的容错。如果可以避免数据库链接失败,则可以避免在应用程序中执行狡猾的错误处理代码。

答案 6 :(得分:10)

,不存在防灾语言。

编辑:

防灾意味着完美。它提醒了一个过程的图像,该过程应用一些智能以逻辑方式解决未知,未指定和意外的情况。编程语言无法通过这种方式实现此目的。如果您作为程序员无法弄清楚程序将如何失败以及如何从程序中恢复,那么您的程序也无法这样做。

从IT角度来看,灾难可以以如此多的方式出现,以至于没有任何一个流程可以解决所有这些不同的问题。您可以设计一种语言来解决出现问题的所有方法的想法是错误的。由于硬件的抽象,使用编程语言解决许多问题甚至没有多大意义;但它们仍然是“灾难”。

当然,一旦你开始限制问题的范围;那么我们就可以开始讨论为它开发解决方案了。因此,当我们停止谈论防灾并开始谈论从意外的电涌中恢复时,开发一种编程语言以解决这个问题变得更加容易,即使在处理该问题时也许没有多大意义。如此高水平的堆栈。但是,我会冒险预测,一旦你将其范围缩小到实际的实现,它就会变得无趣,因为它变得非常具体。即使用我的脚本语言在一夜之间运行批处理过程,这些过程将从意外的电涌和网络连接丢失中恢复(有一些人工协助);这对我来说并不是一个引人注目的商业案例。

请不要误解我。在这个帖子中有一些很好的建议,但在我看来,他们甚至没有任何东西,甚至远程接近防灾。

答案 7 :(得分:4)

考虑使用非易失性存储器构建的系统。程序状态始终保持不变,如果处理器停止任何时间长度,它将在重新启动时停止的位置恢复。因此,您的程序可以“防灾”,只要能够在电源故障中存活下来。

这是完全可能的,正如其他帖子在讨论软件事务内存和“容错”等时所概述的那样。好奇的人没有提到'忆阻器',因为他们会提供具有这些属性的未来架构,也许不是完全是冯·诺伊曼建筑。

现在想象一个由两个这样的离散系统构建的系统 - 为了直观说明,一个是数据库服务器,另一个是在线银行网站的应用服务器。

如果一个人暂停,另一个人会做什么?它是如何处理它的同事突然无法使用的?

它可以在语言级别处理,但这意味着很多错误处理等等,并且这是一个棘手的代码来实现。这几乎没有比我们今天更好的地方,机器没有检查指向,但语言尝试并检测问题,并要求程序员处理它们。

它也可以暂停 - 在硬件层面它们可以捆绑在一起,这样从功率角度来看它们就是一个系统。但这不是一个好主意;更好的可用性将来自具有备份系统等的容错架构。

或者我们可以在两台机器之间使用持久性消息队列。但是,在某些时候这些消息会被处理掉,而且它们可能在那时太老了!在这种情况下,只有应用程序逻辑才能真正发挥作用,我们又回到了再次委托给程序员的语言。

因此,目前形式的防灾似乎更好 - 不间断的电源,准备好的热备份服务器,主机之间的多个网络路由等等。然后我们只需要希望我们的软件是错误的 - 免费电话

答案 8 :(得分:3)

准确答案:

AdaSPARK旨在实现最大容错能力,并将所有错误移至编译时而非运行时。 Ada由美国国防部设计用于军事和航空系统,在飞机等嵌入式设备上运行。 Spark是它的后代。在早期的美国太空计划中使用了另一种语言,HAL / S用于处理由于宇宙射线导致的硬件故障和内存损坏。


实际答案:

我从来没有见过能编码Ada / Spark的人。对于大多数用户而言,最佳答案是DBMS上的SQL变体,具有自动故障转移和服务器群集。完整性检查确保安全。像T-SQL或PL / SQL这样的东西具有完全的事务安全性,是Turing-complete,并且非常容忍问题。


原因没有更好的答案:

出于性能原因,您无法为每个程序操作提供持久性。如果你这样做,处理速度会降低到最快的非易失性存储速度。充其量,你的性能将下降一千或几百万,因为任何比CPU缓存或RAM慢多少。

这相当于从Core 2 Duo CPU到古老的8086 CPU - 最多每秒可以执行几百次操作。除此之外,这甚至会更低。

如果存在频繁的电源循环或硬件故障,您可以使用DBMS之类的东西来保证每个重要操作的ACID。或者,您使用具有快速非易失性存储(例如闪存)的硬件 - 这仍然要慢得多,但如果处理很简单,那就没关系。

充其量,您的语言为错误提供了良好的编译时安全检查,并且会抛出异常而不是崩溃。异常处理是现在使用的一半语言的一个特性。

答案 9 :(得分:3)

答案 10 :(得分:3)

有几个商业上可用的框架Veritas,Sun的HA,IBM的HACMP等。 这将自动监视进程并在发生故障时在另一台服务器上启动它们。

还有昂贵的硬件,如HP Tandem Nonstop系列,可以承受内部硬件故障。

然而,软件是由人民建立的,人们喜欢把它弄错。考虑IBMs MVS附带的IEFBR14程序的警示故事。它基本上是一个NOP虚拟程序,允许JCL的声明位在没有真正运行程序的情况下发生。这是完整的原始源代码: -

     IEFBR14 START
             BR    14       Return addr in R14 -- branch at it
             END

没有什么代码更简单?在其长期使用期间,该程序实际上已经编写了一个错误错误报告,现在是版本4。

这是三行代码的1个错误,当前版本是原始版本的四倍。

错误总会蔓延,只要确保你可以从中恢复。

答案 11 :(得分:2)

  

它的主要特征应该是:如果电源耗尽,并且事情重新启动它就会从它停止的地方开始(因此它不仅会记住它的位置,它还会记住变量状态)。此外,如果它在文件复制过程中停止,它也将正确恢复。等等。

     

......

     

我过去看过erlang。不管它有什么样的容错功能......它无法在断电中存活下来。当代码重新启动时,你将不得不拿起碎片

如果存在这样的技术,我会非常有兴趣阅读它。也就是说,Erlang解决方案将拥有多个节点 - 理想情况下位于不同的位置 - 这样,如果一个位置发生故障,其他节点就可以获得松弛。如果您的所有节点位于相同的位置并且位于相同的电源上(对于分布式系统来说不是一个好主意),那么您将在评论后续跟踪中提到的运气不好。

答案 12 :(得分:2)

Microsoft Robotics Group推出了一组似乎适用于您的问题的库。

  

什么是并发和协调   运行时间(CCR)?

     

并发和协调运行时   (CCR)提供高度并发   基于XML的编程模型   消息传递功能强大   编排原语启用   无需协调数据和工作   使用手动穿线,锁,   信号量等.CCR解决了这个问题   需要多核和并发   提供的应用程序   方便的编程模型   管理异步操作,   处理并发,利用   并行硬件和处理部分   故障。

     

什么是分散式软件   服务(DSS)?

     

分散式软件服务(DSS)   提供轻量级,面向状态   结合的服务模式   代表性国家转移(REST)   有一个正式的组成和   事件通知架构   启用系统级方法   建筑应用。在DSS中   服务作为资源公开   哪两个都可以访问   以编程方式和UI   操纵。通过整合服务   构成,结构化的国家   操纵和事件通知   通过数据隔离,DSS提供了一个   高度写作的统一模式   可观察的,松散耦合的   在单个节点上运行的应用程序   或者通过网络。

给出的大多数答案都是通用语言。您可能希望研究嵌入式设备中使用的更专业的语言。机器人是一个值得思考的好例子。从电源故障中恢复后,您想要和/或期望机器人做什么?

答案 13 :(得分:2)

在嵌入式领域,这可以通过看门狗中断和电池供电的RAM来实现。我自己写过。

答案 14 :(得分:2)

尝试使用现有的开源解释语言,看看是否可以调整其实现以包含其中一些功能。 Python的默认C实现嵌入了一个内部锁(称为GIL,全局解释器锁),用于通过轮流每个'n'VM指令来“处理”Python线程之间的并发。也许您可以使用相同的机制来检查代码状态。

答案 15 :(得分:2)

根据您对灾难的定义,将此责任委托给该语言的范围可以从“困难”到“实际上不可能”。

给出的其他示例包括在执行每个语句后将应用程序的当前状态持久保存到NVRAM。这只有在计算机不被破坏时才有效。

如何知道在新主机上重启应用程序的语言级别功能?

在将应用程序恢复到主机的情况下 - 如果已经过了大量时间并且先前做出的假设/检查现在无效,该怎么办?

T-SQL,PL / SQL和其他交易语言可能与“灾难证明”一样接近 - 它们要么成功(并且数据被保存),要么它们没有。排除禁用事务隔离,如果你真的努力尝试进入'未知'状态很困难(但可能并非不可能)。

您可以使用SQL镜像等技术来确保在提交事务之前将写入同时保存在至少两个位置。

您仍然需要确保每次安全(提交)时保存您的状态。

答案 16 :(得分:2)

如果程序在机器断电的情况下继续停止运行,不仅需要将状态保存到某处,操作系统还必须“知道”才能恢复它。 / p>

我想在语言中实现一个“休眠”功能可以完成,但是在后台不断发生这种情况,所以在发生任何不良事件的情况下,我认为这就像操作系统的工作一样。

答案 17 :(得分:2)

如果故障模式仅限于硬件故障,VMware Fault Tolerance声称您想要的类似事情。它在多个集群中运行一对虚拟机,并使用他们称之为vLockstep的虚拟机,主vm将所有状态实时发送到辅助虚拟机,因此在主要故障的情况下,执行将透明地翻转到辅助虚拟机。

我的猜测是,这无助于通信故障,这比硬件故障更常见。对于严重的高可用性,您应该考虑像Birman的流程组方法(paper in pdf format或书籍Reliable Distributed Systems: Technologies, Web Services, and Applications )这样的分布式系统。

答案 18 :(得分:2)

如果我正确理解了您的问题,我认为您在询问是否可以保证特定算法(即程序加上环境提供的任何恢复选项)将完成(在任意数量的恢复之后/重新启动)。

如果这是正确的,那么我会推荐你​​halting problem

  

给定程序和有限输入的描述,根据输入确定程序是否完成运行或将永远运行。

我认为将你的问题归类为暂停问题的一个例子是公平的,因为你会理想地将语言称为“防灾” - 也就是说,给任何有缺陷的程序或混乱的环境赋予“完美”。

这种分类将环境,语言和程序的任何组合减少为“程序和有限输入”。

如果你同意我的意见,那么你会感到失望的是,这个停顿问题是不可判定的。因此,没有“防灾”语言或编译器或环境可以证明是这样的。

但是,设计一种为各种常见问题提供恢复选项的语言是完全合理的。

答案 19 :(得分:2)

在电源故障的情况下......听起来像我:“当你唯一的工具是锤子时,每个问题看起来都像钉子一样”

您无法解决程序中的电源故障问题。您可以使用备用电源,电池等解决此问题。

答案 20 :(得分:1)

最接近的似乎是SQL。然而,这不是一个真正的语言问题;它主要是一个VM问题。我可以想象具有这些属性的Java VM;实施它将是另一回事。

通过应用程序检查点实现快速和肮脏的近似。你失去了“随时死亡”的财产,但它非常接近。

答案 21 :(得分:0)

Windows Workflow Foundation可以解决您的问题。它基于.Net,并以图形方式设计为具有状态和操作的工作流程。

它允许对数据库进行持久化(自动或在提示时)。您可以在状态/操作之间执行此操作。这会将工作流的整个实例序列化到数据库中。它将被重新水合,当满足任何条件时(某些时间,以编程方式重新水化,事件发生等等),执行将继续执行。

当WWF主机启动时,它会检查持久性DB并重新水化存储在那里的所有工作流程。然后它继续从持久性的角度执行。

即使您不想使用工作流方面,您仍然可以使用持久性服务。

只要您的步骤是原子的,这应该足够了 - 特别是因为我猜你有一台UPS,因此可以监控UPS事件,并在检测到电源问题时强制持久。

答案 22 :(得分:0)

如果我要解决你的问题,我会编写一个守护进程(可能在C中),它在事务中完成所有数据库交互,因此如果它被中断,你将不会得到任何错误的数据。然后让系统在启动时启动此守护程序。

显然,在C语言中开发Web内容比在脚本语言中使用它要慢得多,但它会表现得更好并且更稳定(如果你编写好的代码当然:)。

实际上,我用Ruby(或PHP或其他)编写它,并且经常运行Delayed Job(或cron或任何调度程序),因为我不需要在时钟周期内更新内容。

希望这是有道理的。

答案 23 :(得分:0)

  • 首先,实现容错应用程序。如果您有8个功能和5个故障模式,那么您已经完成了分析和测试,以证明所有40个组合按预期工作(并且根据具体客户的需要:没有两个可能会同意)。
  • 第二,在支持的容错功能集之上添加脚本语言。它需要尽可能接近无国籍,所以几乎肯定是非图灵完成的东西。
  • 最后,找出如何处理适用于每种故障模式的脚本语言状态的恢复和修复。

是的,这几乎是rocket science

答案 24 :(得分:0)

在我看来,失败恢复的概念大多数时候是业务问题,而不是硬件或语言问题。

举个例子:你有一个UI层和一个子系统。 子系统不是很可靠,但UI层上的客户端应该像它一样完善它。

现在,想象一下你的子系统崩溃了,你真的认为你想象的语言可以根据这个子系统为你考虑如何处理UI层吗?

您的用户应该明确意识到子系统不可靠,如果您使用消息传递来提供高可靠性,客户端必须知道(如果他不知道,UI可以只是冻结等待最终会出现的响应2周后)。如果他应该意识到这一点,这意味着任何隐藏它的abstration最终都会泄漏。

客户端,我的意思是最终用户。用户界面应该反映出这种不可靠性而不是隐藏它,在这种情况下,计算机无法为你思考。

答案 25 :(得分:0)

“所以这种语言会记住它在任何特定时刻的状态,无论权力被切断,还是从中断的地方继续。”

“继续停止的地方”通常不是正确的恢复策略。世界上没有任何语言或环境会试图猜测如何自动从特定故障中恢复。它能做的最好的事情就是为您提供工具,以不干扰业务逻辑的方式编写自己的恢复策略,例如。

  • 异常处理(快速失败并仍然确保状态的一致性)
  • 交易(回滚未完成的更改)
  • 工作流程(用于定义自动调用的恢复例程)
  • 记录(用于追踪故障原因)
  • AOP /依赖注入(以避免必须手动插入代码来执行上述所有操作)

这些是非常通用的工具,有很多语言和环境可供选择。

答案 26 :(得分:0)

如果您确实希望保存程序信息,您会在哪里保存?

需要保存,例如到磁盘。但是如果磁盘发生故障,这对你没有帮助,所以它已经不是防灾了。

您只能在保存状态下获得一定程度的粒度。如果你想要像tihs这样的东西,那么最好的方法可能是根据构成原子操作的内容来定义粒度级别,并在每次原子操作之前将状态保存到数据库。然后,您可以恢复到该级别原子操作的点。

我不知道任何会自动执行此操作的语言,因为将状态保存到二级存储的成本非常高。因此,在粒度级别和效率之间存在权衡,这在任意应用程序中很难定义。

答案 27 :(得分:0)

我认为恢复的一个根本错误不是一个突出的设计问题。独家承担环境责任导致一般性脆弱的解决方案不容忍内部缺陷。

如果是我,我会投资可靠的硬件并以一种能够在任何可能的条件下自动恢复的方式设计软件。根据您的示例,数据库会话维护应由足够高级别的API自动处理。如果您必须手动重新连接,则可能使用了错误的API。

正如其他人所指出的那样,嵌入在现代RDBMS系统中的程序语言是您在不使用外来语言的情况下获得的最佳选择。

VM通常是为此类设计的。您可以使用VM供应商(vmware..et al)API来控制应用程序中的定期检查点。

VMWare特别具有重放功能(增强执行记录),可记录一切并允许时间点播放。显然,这种方法会对性能产生巨大影响,但它可以满足要求。我只是确保你的磁盘驱动器有一个备用电池的写缓存。

您很可能能够找到在java虚拟机中运行的java字节码的类似解决方案。 Google容错JVM和虚拟机检查点。