您好、欢迎来到现金彩票网!
当前位置:星彩网 > 分布式存储器 >

分布式消息通信Kafka-原理分析

发布时间:2019-05-11 09:03 来源:未知 编辑:admin

  在 kafka 中,topic 是一个存储消息的逻辑概念,可以认为是一个消息集合。

  每条发送到 kafka 集群的消息都有一个类别。物理上来说,不同 topic 的消息是分开存储的,每个 topic 可以有多个生产者向它发送消息,也可以有多 个消费者去消费其中的消息。

  每个 topic 可以划分多个分区(每个 Topic 至少有一个分区),同一 topic 下的不同分区包含的消息是不同的。

  每个消息在被添加到分区时,都会被分配一个 offset(偏移量),它是消息在此分区中的唯一编号,kafka 通过 offset 保证消息在分区内的顺序,offset 的顺序不跨分区,即 kafka 只保证在同一个分区内的消息有序。

  每一条消息发送到 broker 时,会根据 partition 的规则选择存储到哪一个 partition。如果 partition 规则设置合理,那么所有的消息会均匀的分布在不同的 partition 中, 这样就有点类似数据库的分库分表的概念,把数据做了分片处理。

  在 kafka 中,一条消息由 key、value 两部分构成,在发送一条消息时,我们可以指定这个 key,那么 producer 会根据 key 和 partition 机制来判断当前这条消息应该发送并存储到哪个 partition 中.

  如果 Key 为 null,则会随机分配一个分区。这个随机是在这个参 数metadata.max.age.ms的时间范围内随机选择一个。

  对于这个时间段内,如果 key 为 null,则只会发送到唯一的分区。该值默认情况下10 分钟更新一次。

  通过下面的代码,就可以消费指定该 topic 下的 0 号分区。 其他分区的数据就无法接收

  一方面能够对 broker 上的数据进行分片,有效减少了消息的容量从而提升 I/O 性能

  另外,为了提高消费端的消费能力,一般会通过多个 consumer 去消费同一个 topic ,也就是消费端的负载均衡机制,也就是我们接下来要了解的,在多个 partition 以 及多个 consumer 的情况下,消费者是如何消费消息的

  组内的所有消费者协调在一起来消费订阅主题的所有分区。当然每一个分区只能由同一个消费组内的 consumer 来消费,那么同一个 consumer group 里面的 consumer 是如何分配该消费哪个分区里的数据的呢?

  通过前面的案例演示,我们应该能猜到,同一个 group 中的消费者对于一个 topic 中的多个 partition,存在一定的分区分配策略.

  Range 策略是对每个主题而言的,首先对同一个主题里面的分区按照序号进行排序,并对消费者按照字母顺序进行 排序。

  然后将 partitions 的个数除以消费者线程的总数来决定每个消费者线程消费几个分区。

  在我们的例子里面,我们有 10 个分区,3 个消费者线,且除不尽,那么消费者线 将会多消费一 个分区,所以最后分区分配的结果看起来是这样的:

  假如我们有 2 个主题(T1 和 T2),分别有 10 个分区,那么最后分区分配的结果看起来是这样的:

  可以看出,C1-0 消费者线程比其他消费者线 个 分区,这就是 Range strategy 的一个很明显的弊端

  轮询分区策略是把所有 partition 和所有 consumer 线程都列出来,然后按照 hashcode 进行排序。最后通过轮询算法分配 partition 给消费线程。如果所有 consumer 实例的订阅是相同的,那么 partition 会均匀分布。

  消费者离开当前所属的 consumer group,比如主动停机或者宕机

  而具体如何执行分区策略,就是前面提到过的两种内置的分区策略。而 kafka 对于分配策略这块,提供了可插拔的实现方式, 也就是说,除了这两种之外,我们还可以创建自己的分配机制。

  每个消费者都会向 coordinator 发送 syncgroup 请求,不 过只有 leader 节点会发送分配方案,其他消费者只是打打酱油而已。

  前面在讲解 partition 的时候,提到过 offset, 每个 topic可以划分多个分区(每个 Topic 至少有一个分区),同一 topic 下的不同分区包含的消息是不同的。

  每个消息在被添加到分区时,都会被分配一个 offset(称之为偏移量),它是消息在此分区中的唯一编号,kafka 通过 offset 保证消息 在分区内的顺序,offset 的顺序不跨分区,即 kafka 只保证在同一个分区内的消息是有序的

  对于应用层的消费来说, 每次消费一个消息并且提交以后,会保存当前消费到的最近的一个 offset。那么 offset 保存在哪里?

  从输出结果中,我们就可以看到 test 这个 topic 的 offset 的位移日志

  首先我们需要了解的是,kafka 是使用日志文件的方式来保存生产者和发送者的消息,每条消息都有一个 offset 值来表示它在分区中的偏移量。

  Kafka 中存储的一般都是海量的消息数据,为了避免日志文件过大,Log 并不是直接对应在一个磁盘上的日志文件,而是对应磁盘上的一个目录, 这个目录的命名规则是

  了解到这里的时候,大家再结合前面讲的消息分发策略, 就应该能明白消息发送到 broker 上,消息会保存到哪个分区中,并且消费端应该消费哪些分区的数据了。

  我们现在大部分企业仍然用的是机械结构的磁盘,如果把消息以随机的方式写入到磁盘,那么磁盘首先要做的就是寻址,也就是定位到数据所在的物理地址,在磁盘上就要找到对应的柱面、磁头以及对应的扇区;这个过程相对内 存来说会消耗大量时间,为了规避随机读写带来的时间消耗,kafka 采用顺序写的方式存储数据。

  即使是这样,但是频繁的 I/O 操作仍然会造成磁盘的性能瓶颈,所以 kafka 还有一个性能策略

  消息从发送到落地保存,broker 维护的消息日志本身就是文件目录,每个文件都是二进制保存,生产者和消费者使用相同的格式来处理。在消费者获取消息时,服务器先从硬盘读取数据到内存,然后把内存中的数据原封不动的通 过 socket 发送给消费者。

  ▪ 操作系统将数据从 socket 缓冲区复制到网卡缓冲区,以便将数据经网络发出

  这个过程涉及到 4 次上下文切换以及 4 次数据复制,并且有两次复制操作是由 CPU 完成。但是这个过程中,数据完全没有进行变化,仅仅是从磁盘复制到网卡缓冲区。

  通过“零拷贝”技术,可以去掉这些没必要的数据复制操作, 同时也会减少上下文切换次数。现代的 unix 操作系统提供 一个优化的代码路径,用于将数据从页缓存传输到 socket; 在 Linux 中,是通过 sendfile 系统调用来完成的。

  使用 sendfile,只需要一次拷贝就行,允许操作系统将数据直接从页缓存发送到网络上。所以在这个优化的路径中, 只有最后一步将数据拷贝到网卡缓存中是需要的返回搜狐,查看更多

http://emeklishop.net/fenbushicunchuqi/227.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有