(一)消息队列模型和发布/订阅模型
最常见的两种消息引擎范型是消息队列模型和发布/订阅模型。
消息队列(message queue)模型是基于队列提供消息传输服务的,多用于进程间通信(inter-process communication,IPC)以及线程间通信。该模型定义了消息队列(queue)、发送者(sender)和接收者(receiver)提供了一种点对点(point-to-point,p2p)的消息传递方式,即发送者发送每条消息到队列的指定位置,接收者从指定位置获取消息。一旦消息被消费(consumed),就会从队列中移除该消息。每条消息由一个发送者生产出来,且只被一个消费者(consumer)处理-发送者和消费者之间是一对一的关系。生活中接线生的工作就是一个典型的基于队列的消息引擎模型。每个打进来的电话都进入一个排队队列,然后只由一个接线生进行处理。同一个客户不会被第二个接线生处理。
而另一种模型就是发布/订阅模型(publish/subscribe,或简称为pub/sub),与前一种模型不同,它有主题 (topic的概念:一个 topic 可以理解为逻辑语义相近的消息的容器。这种模型也定义了类似于生产者/消费者这样的角色,即发布者(publisher)和订阅者(subscriber)发布者将消息生产出来发送到指定的 topic 中,所有订阅了该 topic 的订阅者都可以接收到该topic 下的所有消息。通常具有相同订阅 topic 的所有阅者将接收到同样的消息,如图 1.4所示。生活中报纸的订阅就是一种典型的发布/订阅模型:很多读者都会订阅同一个报社(类比于同一个 topic)出版的报纸,这样每当报纸更新(生产新的消息)时,这些读者都可以收到最新的报纸(接收最新的消息)。
(二)吞吐量
吞吐量是某种处理能力的最大值。而对于 Kafka而言,它的吞吐量就是每秒能够处理的消息数或者每秒能够处理的字节数。
Kafka就是依靠下列4点达到了高吞吐量、低延时的设计目标的。
大量使用操作系统页缓存,内存操作速度快且命中率高。
Kafka不直接参与物理IO操作,而是交由最擅长此事的操作系统来完成
采用追加写入方式,摒弃了缓慢的磁盘随机读/写操作。
使用以sendfile为代表的零拷贝技术加强网络间的数据传输效率。
(三)消息持久化
Kafka是要持久化消息的,而且要把消息持久化到磁盘上。这样做的好处如下。
解耦消息发送与消息消费:本质上来说,Kaka 最核心的功能就是提供了生产者-消费者模式的完整解决方案。通过将消息持久化使得生产者方不再需要直接和消费者方耦合,它只是简单地把消息生产出来并交由 Kafka 服务器保存即可,因此提升了整体的吞吐量
实现灵活的消息处理:很多Kafka的下游子系统(接收 Kafka消息的系统)都有这样的需求一对于已经处理过的消息可能在未来的某个时间点重新处理一次,即所谓的消息重演(messagereplay)。消息持久化便可以很方便地实现这样的需求
(四)负载均衡
何为负载均衡?顾名思义就是让系统的负载根据一定的规则均衡地分配在所有参与工作的服务器上,从而最大限度地提升系统整体的运行效率。具体到Kafka来说,默认情况下 Kafka的每台服务器都有均等的机会为 Kaka的客户提供服务,可以把负载分散到所有集群中的机器上,避免出现“耗尽某台服务器”的情况发生。
Kafka实现负载均衡实际上是通过智能化的分区领导者选举(partition leader election)来实现的。Kafka 默认提供了很智能的 leader 选举算法,可以在集群的所有机器上以均等机会分散各个partition的leader,从而整体上实现了负载均衡。
(五)故障转移
除了负载均衡,完备的分布式系统还需要支持故障转移。所谓故障转移,是指当服务器意外中止时,整个集群可以快速地检测到该失效 (failure),并立即将该服务器上的应用或服务自动转移到其他服务器上。故障转移通常是以“心跳”或“会话”的机制来实现的,即只要主服务器与备份服务器之间的心跳无法维持或主服务器注册到服务中心的会话超时过期了,那么就认为主服务器已无法正常运行,集群会自动启动某个备份服务器来替代主服务器的工作Kafka服务器支持故障转移的方式就是使用会话机制。每台Kafka服务器启动后会以会话的形式把自己注册到ZooKeeper服务器上。一旦该服务器运转出现问题,与ZooKeeper的会话便不能维持从而超时失效,此时 Kafka集群会选举出另一台服务器来完全代替这台服务器继续提供服务
(六)
有了消息的持久化,Kafka 实现了高可靠性:
有了负载均衡和使用文件系统的独特设计Kafka 实现了高吞吐量;
有了故障转移,Kafka 实现了高可用性。
(七)伸缩性
伸缩性表示向分布式系统中增加额外的计算资源(比如CPU、内存、存储或带宽)时吞吐量提升的能力。
举一个例子来说,对于计算密集型(computation-intensive)的业务而言,CPU的消耗一定是最大的,这类系统上的操作我们称之为CPU-bound。那么如果一个CPU的运算能力是 U,我们自然希望两个 CPU的运算能力是2U,即可以线性地扩容计算能力,这种线性伸缩性是最理想的状态,但在实际中几乎不可能达到,毕竟分布式系统中有很多隐藏的“单点”瓶颈制约了这种线性的计算能力扩容。
阻碍线性扩容的一个很常见的因素就是状态的保存。我们知道,不论是哪类分布式系统,集群中的每台服务器一定会维护很多内部状态。如果由服务器自己来保存这些状态信息,则必须要处理一致性的问题。相反,如果服务器是无状态的,状态的保存和管理交于专门的协调服务来做(比如 ZooKeeper),那么整个集群的服务器之间就无须繁重的状态共享,这极大地降低了维护复杂度。倘若要扩容集群节点,只需简单地启动新的节点机器进行自动负载均衡就可以了。
Kafka正是采用了这样的思想--每台 Kafka 服务器上的状态统一交由 ZoKeeper 保管。扩展 Kafka 集群也只需要一步:启动新的 Kafka 服务器即可。当然这里需要言明的是,在Kafka 服务器上并不是所有状态都不保存,它只保存了很轻量级的内部状态,因此在整个集群间维护状态一致性的代价是很低的。
(八)
生产者发送消息给Kafka服务器
消费者从 Kafka服务器读取消息
Kafka服务器依托ZooKeeper集群进行服务的协调管理。
《 Apache Kafka实战》
如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!
添加我为好友,拉您入交流群!
请使用微信扫一扫!