如何使我的应用程序扩展良好?

时间:2008-09-03 09:30:40

标签: algorithm language-agnostic scalability

一般而言,哪种设计决策有助于应用程序扩展?

(注意:刚刚了解了Big O Notation,我想在这里收集更多编程原则。我试图通过回答下面的问题来解释Big O Notation,但我希望社区能够改善这个问题和答案。)

到目前为止的回复
1)定义缩放。您是否需要扩展虚拟环境中的大量用户,流量和对象? 2)看看你的算法。他们的工作量是否与实际工作量成线性关系 - 即要循环的项目数量,用户数量等等?
3)看看你的硬件。您的应用程序是否设计为可以在多台计算机上运行,​​如果无法跟上?

次要想法
1)不要过早优化太多 - 先测试一下。也许瓶颈会发生在不可预见的地方 2)也许扩展的需要不会超过摩尔定律,也许升级硬件会比重构更便宜。

7 个答案:

答案 0 :(得分:11)

我唯一要说的就是编写应用程序,以便可以从一开始就将其部署在集群上。以上任何事情都是过早的优化。您的第一份工作应该是让足够多的用户遇到扩展问题。

尽可能简单地构建代码,然后对系统进行概要分析,并仅在存在明显性能问题时进行优化。

通常,分析代码的数据反直觉;瓶颈往往存在于你认为不会很慢的模块中。在优化方面,数据是最重要的。如果你优化了你认为会很慢的部件,你通常会优化错误的东西。

答案 1 :(得分:6)

答案 2 :(得分:4)

这个名为High Scalibility的博客包含了很多有关此主题的信息。一些有用的东西。

答案 3 :(得分:3)

通常,最有效的方法是通过深思熟虑的设计,其中缩放是其中的一部分。

确定缩放对您的项目实际意味着什么。是无限量的用户,是否能够在网站上处理slashdotting是开发周期吗?

使用此功能来集中您的开发工作

答案 4 :(得分:2)

Jeff和Joel在Stack Overflow Podcast #19中讨论了缩放问题。

答案 5 :(得分:1)

一个好主意是确定每个附加任务创建的工作量。这可能取决于算法的结构。

例如,假设您在城市中有一些虚拟汽车。在任何时候,您都希望每辆车都有一张地图,显示所有车辆的位置。

解决这个问题的一种方法是:

    for each car {
       determine my position;  
       for each car {  
         add my position to this car's map;  
       }
    }

这看起来很简单:看看第一辆车的位置,将其添加到其他车的地图上。然后看看第二辆车的位置,将其添加到其他车的地图上。等

但是存在可扩展性问题。当有2辆车时,这个策略需要4个“加我位置”的步骤;当有3辆车时,需要9步。 对于每个“位置更新”,您必须遍历整个汽车列表 - 每辆汽车都需要更新其位置。

忽略每辆汽车必须完成的其他事情(例如,计算单个汽车的位置可能需要一定的步数),对于N辆汽车,需要N 2 “访问汽车”运行此算法。当你有5辆车和25步时,这没问题。但是当你添加汽车时,你会看到系统陷入困境。 100辆汽车将需要10,000步,101辆汽车将需要10,201步!

更好的方法是撤消for循环的嵌套。

    for each car {  
      add my position to a list;  
    }  
    for each car {    
      give me an updated copy of the master list;  
    }

采用这种策略,步数是N的倍数,而不是N 2 因此100辆汽车将需要100倍于1辆汽车的工作 - 而不是工作的10,000倍

这个概念有时以“大O符号”表示 - 所需的步数是“N的大O”或“N 2 的大O”。

请注意,此概念仅涉及可扩展性 - 不优化每辆车的步数。在这里我们不关心每辆车需要5步或50步 - 主要是N车采取(X * N)步骤,而不是(X * N 2 )。

答案 6 :(得分:1)

FWIW,大多数系统都会通过忽略它来实现最有效的扩展,直到它成为一个问题 - 摩尔定律仍然存在,除非你的流量增长速度超过摩尔定律,否则购买更大的盒子通常会更便宜(2美元或者每个3美元一个流行音乐比支付给开发者。

尽管如此,最关注的重点是您的数据层;这是您的应用程序中最难扩展的部分,因为它通常需要具有权威性,并且集群商业数据库非常昂贵 - 开源变体通常非常难以实现。

如果您认为您的应用程序很可能需要扩展,那么在开发过程中相对较早地查看memcached或map等系统可能是明智的。