(消息传递)队列如何可扩展?

How can (messaging) queue be scalable?

我经常在软件架构中看到队列,尤其是那些被称为 "scalable" 的队列,具有来自 Akka.io 多角色平台的 Actor 的突出代表。但是,如果我们必须同步将消息放入队列(因此​​在单线程与多线程中操作)并再次同步从队列中取出消息(以确保该消息恰好被取出一次),那么队列如何可扩展?它变得更加复杂,当这些消息可以改变(参与者)系统的状态时——在这种情况下,即使从队列中取出消息后,它也不能进行负载平衡,但仍然在单线程中处理。

  1. 消息入队列必须同步,对吗?
  2. 消息出队列是否必须同步?
  3. 如果 1 或 2 是正确的,那么队列如何扩展?同步到单线程不会立即造成瓶颈吗?
  4. 如果(参与者)系统是有状态的,它如何可扩展?
  5. statefull actor/bean 是否意味着我必须在单线程中按顺序处理消息?
  6. 全状态是否意味着每个整个系统我必须有一个 bean/actor 副本?
  7. 如果 6 为假,那么如何在实例之间共享此状态?
  8. 当我尝试将我的新 P2P 节点连接到网络时,我相信我必须有一些 "server" 会告诉我,谁是其他节点,这是正确的吗?当我尝试下载 torrent 时,我必须连接到跟踪器 - 如果有 "server" 那么我们称它为 P2P 吗?如果此跟踪器出现故障,那么我将无法连接到对等设备,对吗?
  9. 同步和全状态是否会破坏可伸缩性?
  1. Is it correct, that putting messages in queue must be synchronized?
  2. Is it correct, that putting messages out of queue must be synchronized?

没有

假设我们谈论的是 synchronized java 关键字,那么这是对象上的可重入互斥锁。只要 contention 低,即使是多个线程访问该锁也可以很快。而且每个对象都有自己的锁,所以有很多锁,每个锁只需要很短的时间,即是细粒度锁定。

但即使有,也不需要通过互斥锁来实现队列。 Lock-free and even wait-free 存在队列数据结构。这意味着仅仅存在锁并不会自动暗示单线程执行。

您的其余问题应单独提出,因为它们与消息队列无关。

当然你是对的,因为单个队列是不可扩展的。 Actor 模型的要点是您可以拥有数百万个 Actors,因此可以将负载分布到数百万个队列上——如果您的集群中有这么多核心。永远记住 Carl Hewitt 所说的话:

One Actor is no actor. Actors come in systems.

每个单独的参与者都是一个完全顺序的单线程计算单元。不过,整个模型的构造使其非常适合描述分布;这意味着您可以根据需要创建尽可能多的演员。