RELATEED CONSULTING
相关咨询
选择下列产品马上在线沟通
服务时间:9:30-18:00
你可能遇到了下面的问题
关闭右侧工具栏

技术支持

不要立即检查刚做过的工作
  • 作者:技术小林
  • 发表时间:2018-07-19 14:37
  • 来源:未知

  不要立即检查刚做过的事情,也不要立即读刚写过的数据。绝对不要为了验证而立即读刚写过的数据。为了近期内的运维需要,可以把数据存储在本地或分布式的缓存中。验证工作相对于不太可能出现的故障来说成本更高。这种活动有悖于有效扩展的需求。

  木匠有句名言:“量两次,锯一次。”你可能从中学的木工老师那里听过这句话一他可能还缺了根手指。抛开少手指这事不说,这句名言还是很有道理的,正所谓实践出真知。最好在切割前验证测量的准确度,因为错误的测量结果会导致生产浪费,例如切出一块大小不对的木板。我们当然不会那么做。然而,我们所要强调的是怎样减少另一种浪费,即立即验证刚写入的数据。

  在过去的几年中,我们发现自己常常会问客户:“读并验证刚写人的数据,你认为这真的有意义吗?”这种问题出的率令我们吃惊。有时,客户的理由很充分,但没有一条是我们认同的。通常,客户看起来就像是那种被当场抓住的知道自己做了不该做的事的孩子。那些对回答经过深思熟虑(虽然在我们看来是破坏了价值)的客户声称,他们的应用需要绝对确保数据不只是被写入了,还要写得正确。但要记住,我们绝大多数客户都有SaS或商务平台,他们不是在运行核电站,也不是要把人类送往太空,更不是在控制几千架客机的起落或治疗癌症。对于写错或者计算错数据的恐惧,一直都是耗费开发者额外时间的主因。这种恐惧在计算的早期发展阶段可能还算合理,Tanden和Stratus公司分别在20世纪70年代末期和80年代初期设计容错计算机就与这种恐惧有着定的关系。这种系统的主要意图是减少系统的平均故障时间(MTTF),采用的方法是“冗余一切”,即包括CPU、存储、内存、内存路径和存储路径等在内的所有设备都有冗余。这种模型必须对并行计算和存储的系统的结果进行对比,才能验证系统在正确运行。本书的一位作者曾经为一台年代久远的Stratus小型计算机开发过应用,在他为此工作的两年中,该系统从来没有出现过两个处理器间的计算错误,也没有出现过写内存或硬盘的错误。

  现在,这种恐惧已经比20世纪70年代末期和80年代初期少多了。事实上,对那些刚写入数据就要执行读操作的客户,当我们问起他们通常是多长时间会发现一次错误时,他们回答得都相当一致,都说从来没有发现过。问题是,除非对由于写操作产生的错误数据进行操作时发生了问题,否则他们绝对不会发现错误。当然,数据损坏也常常发生,但是大多数情况下,只有在真正的写操作时才能发现这种数据损坏。与其投入两倍的工作量,从而让存储、数据库和系统事务减半,不如看看操作返回的错误代码,进行适当的处理。这里补充说明一下,数据损坏的最佳保护措施是正确地做到高可用性,在备用数据库或复制存储设备上保存多个数据副本。最理想的情况是最终实现多个实时站点。

  当然,并非所有的“写后立即读”的操作都是由于过分仔细的程序员为了验证刚写入的数据而产生的。有时,也可能是最终用户请求了刚写人的数据。这里,我们不禁要问:为什么这些客户不把常用的(包括已写入的)数据保存在本地呢?如果刚写入某些数据,而且很可能会再用到这些数据,那么最好把它保存在本地。这种情况一个常见的例子是许多产品中的注册流程。通常,在把用户数据保存为永久注册记录之前,有一个阶段会把这些数据呈现给用户。另一个例子,是许多电子商务站点利用购物车实现的购买流程。无论哪哪种情况,如果你在写入的数据将来还会被用到,那么最好把它们在本地保留一份。关于如何进行缓存以及缓存哪些数据。

  前面论述的重点是要得到一个结论,即重复操作会降低有效扩展的能力。事实上,它会造成事务成本加倍。因此,如果你的解决方案要规避由错误的写操作带来的几百万美金的损失,那可能需要几千万的额外基础设施作保障。根据我们的经验,即使在编程时间和基础设施上投资了,也没办法完全避免这种风险。在大多数情况下,写后即读的操作都是不好的,因为它不只让成本翻倍,限制了扩展性,而且还不能降低风险,从而使成本与收益不相称。毫无疑问,也许会有需要这种操作的地方,但是相比众多技术团队和公司验证过的最佳实践来说,这种情况少之又少。

  细心的读者可能已经发现,我们的原则中存在冲突。需要本地存储的信息代表状态,肯定需要跟服务器保持一致才有用。从宏观角度说,我们同意这种说法,如果一定要做个选择,那么我们会只开发无状态的应用,以确保不会出现写后即读的操作。这说明,我们的原则是常规的,是“通常如此”的,而不是特定的或“唯一正确”的。绝对不要重复你的工作,绝对要维护大型的无状态应用。这两种说法有冲突吗?是的。那么冲突可以解决吗?当然要想解决这一原则冲突,就要站在很高的角度来看。我们既想让系统不浪费资源(如写后即读读),想让系统是无状态的。要实现这一点,我们决定绝对不会为了验证而读数据。我们也同意,有日时为了速度和扩展,我们也希望保持密切关系,而不去读刚写人的数据。这意味着需要维护一些状态信息,但是我们可以把它限制在某些事务中,在这些事务中读刚写入的数据是必要的。虽然这种方法有悖于我们介绍的原则,但是如果这种方法在有限的操作中引1人了状态,从而降低了成本,增加了扩展性,那么它也是可行的。