以并行思维方式思考

许多软件开发人员试图建立可扩展系统时往往会遇到困难。也许这是因为,最简单和最明显的解决方案往往无法扩展; 这可能解释了为什么这些方案有时被称为“幼稚”的解决方案。

一旦你了解并行一些基本概念和准则,在任何情况下,就会编写可伸缩扩展的代码,最重要的是Amdahl定律,你不需要真正理解其背后的数学原理,但理解它的中心思想却是至关重要的,“并行程序受到其组成的串行子部分的限制” - 为此,你必须理解“并行代码”和“串行码'。

要理解并行代码,首先必须了解非并行(串行)代码是什么。作为经验法则,串行代码倾向于做出以下假设:
1.它需要访问所有关于整个问题领域的数据,才能解决问题。
2.它需要在它完成执行的时候才会解决整个问题。

虽然一些问题本质上是串行的,但事实证明许多问题域可以并行化。问题域的解决方案,可以完全并行有时称为“ 易并行 (Embarrassingly parallel)”。

易并行代码可以无限扩展; 串行代码则不能,最终需要重写;因为这一点,有人会说,串行代码设计不良 - 这就是为什么许多开发人员进入函数式编程的原因;Haskell,Erlang和Scala等语言鼓励您编写并行代码(通过避免状态改变和可变数据)。

不幸的是,选择一种特定的编程语言并不够; 编写并行代码,你还需要改变一点你的思维。如果你回想起前面提到的关于串行代码的观点,你可以推断并行代码要求你做出以下假设:
1.它只需要处理它想要解决的整体问题的数据子集。
2.它只需要在它完成执行的时候解决整个问题的一个子集。

在客户端 - 服务器/网络环境中,通常的问题是我们希望处理来自(有时是大量)并发用户的请求(通常是同时读取和/或修改大量的系统数据)。这些类型的问题通常涉及许多不同的(非重叠的)数据集,因此它们可以容易地并行化。

由于hashing , indexing和sharding分片 (均存在数据库和作为应用程序的核心逻辑的一部分); 每个请求的处理可以完全相互隔离 - 这是写易并行代码的关键; 请确保您的代码在任何给定时间只处理整个数据的有限子集。

总结; 并行思考的关键是考虑你的数据是否可由能独立处理的小型、固定大小的数据子集组成的。

为了给你一个实际示例,请考虑以下情况:

我们希望构建一个由两个独立过程组成的实时系统 - 让我们称之为ProcessA和ProcessB。 让我们假设我们有两个用户(Alice和Bob)连接到我们的系统;Alice连接到ProcessA,Bob连接到ProcessB。 我们想要做的是允许Alice向Bob发送消息。 所以问题看起来像这样:

这个问题的一个朴素,非并行(串行)解决方案将是:ProcessA简单地询问ProcessB是否连接到用户'Bob',如果是,ProcessA可以传递消息到ProcessB,然后它将发送给Bob。

当我们的系统中只有两个用户和两个进程时,这个“朴素”的串行解决方案实际上工作得很好,但是如果我们的整体问题看起来像这样:有N多组用户像 Alice和Bob这样进行同时通讯。

在这种情况下你可以想象,processA每次消息通过系统时与每个其他进程进行通信/协调是不可行的; 这意味着我们所有的进程都会一次又一次地对相同的数据(在这种情况下;每条消息)进行操作。

解决这个问题的一个简单的并行算法是pub / sub -有很多方法来实现它,但其背后的核心原则是在不同的通道上划分消息,并跟踪每个通道的订阅者。 pub /sub的典型实现是将涉及跨越多个进程分割通道(使得每个进程处理所有可能的通道名称的子集)。 因此,要在两个或多个用户之间发送消息,您只需将消息发布到适当的频道,即将消息发送到相应的进程(您可以对频道名称进行哈希处理,以确定哪个进程负责该频道),然后过程将该消息转发给相关订户。

使用pub / sub,您可以通过将用户名称(或id)合并到频道名称(例如“alice-channel”,“bob-channel”)中,然后仅允许用户订阅自己的频道频道。 pub / sub背后的“易并行”理念是每个进程只处理通过系统的所有通道和消息的固定子集。您添加的进程越多,每个进程将需要处理的通道/消息越少 - 系统可以处理多少个频道;只要您可以继续添加更多进程(以及运行这些进程的更多硬件)。

除了资源限制,这个pub / sub实现的唯一真正的限制是每个信道的消息吞吐量;但这通常是可接受的限制。 由于消息通常用于人类活动; 每个人每分钟只能消耗这么多的消息 - 实际上,pub / sub的实际限制倾向于接近良好用户体验所需的自然限制 -也就是说,对于高吞吐量(后端/大数据)应用程序,您可以始终将pub / sub通道分成更小的子集,如'alice-channel-1','alice-channel-2',...,'alice-channel-n',而不必对pub /

当然,最终理解并行代码的最好方法是开始动手编写它!希望这篇文章可以给你一个激励,自己试试。

Thinking in Parallel