一、Kafka 数据日志

1.主题 Topic

  Topic 是逻辑概念。

  主题类似于分类,也可以理解为一个消息的集合。每一条发送到 Kafka 的消息都会带上一个主题信息,表明属于哪个主题。

  Kafka 的主题是支持多用户订阅的,即一个主题可以有零个、一个或者多个消费者来订阅该主题的消息。

2.分区 Partition

1)分区原因

  • 方便集群扩展,因为一个 Topic 由多个 Partition 组成,而 Partition 又可以通过调整以适应不同的机器,因而整个集群就可以适应任意大小的数据;
  • 方便提高并发,因为可以以 Partition 为单位进行读写。

2)分区概念

  Partition 是物理概念,一个 Partition 就对应于一个文件夹。

  在 Kafka 中每个主题都可以划分成多个分区,每个主题至少有一个分区,同一个主题的分区之间所包含的消息是不一样的。每个分区只会存在于一个 Broker 上。

  

  每个消息在被添加到分区中的时候,都会带一个 offset(偏移量),它是消息在分区中的编号。通过设置 offset,Kafka 可以保证分区内的消息是有序的,但跨分区的消息是无序的。

  

3)分区策略

  • 在指明 Partition 的情况下,直接将指明的值作为 Partition 的值;
  • 在未指明 Partition 但有 key 的情况下,将 key 的哈希值和该 Topic 中 Partition 的数量进行求余操作,其结果作为 Partition 的值;
  • 在未指明 Partition 的值也没有 key 的情况下,第一次调用时生成一个随机整数,之后在这个整数上自增,将其值和该 Topic 中 Partition 的数量进行求余操作,其结果作为 Partition 的值,即 round-robin 算法。round-robin:轮询调度算法,原理是每一次把来自用户的请求轮流分配给内部中的服务器,从1开始,直到 N(内部服务器个数),然后重新开始循环。

3.数据日志

  

   对于每一个主题,Kafka 保持一个分区日志文件 log,而生产者生产的消息会不断添加到 log 文件末尾,为了防止 log 文件过大导致效率降低,Kafka 采用了分片索引的机制,每个 Partition 分为多个 Segment,每个 Segment 又由两个文件组成 “.index”索引文件“.log”数据文件。这些文件位于一个文件夹下,文件夹的命名规则为:Topic 名称+ Partition 序号,而 index 和 log  文件的命名是根据当前 Segment 的第一条消息的 offset 偏移量来命名的。

  在 index 文件中,是使用 key-value 结构来存储的,key 是 Message 在 log 文件中的编号,value 就是消息值。但是 Index 文件中并没有给每条消息都建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中 。

  

二、Kafka 副本机制

1.副本 Replica

  Replica 是 Partition 的副本。每个 Partition 可以有多个副本,这多个副本之中,只有一个是 leader,其他都是 follower,所有的读写请求都通过 leader 来完成,follower 只负责备份数据。follow 会均匀分配到多个 Broker 上,当 leader 所在的机器挂掉之后,会从 follower 中重新选出一个副本作为 leader 继续提供服务。

  那么为什么有这么多的副本却只使用 leader 来提供服务呢?如果都用上不是可以提高性能吗?这其实就是一致性和可用性之间的取舍了,如果多个副本同时进行读写操作,很容易出现问题。例如在读取消息时,一个消费者没有读取到,而另一个消费者却读取到了,因为这个消费者读取的是 leader 副本,显然这样是不行的。所以为了保证一致性,只使用一个 leader 副本来提供服务。

2.Commit 策略

  Commit:指 leader 通知 Producer ,数据已经成功收到。Kafka 尽量保证 Commit 后即使 leader 挂掉,其他 flower 都有该条数据。

  我们已经知道一个 Partition 可以有多个副本,当有数据写入 leader 时,这些 follower 是怎么复制数据的?下面是两种策略:

  • 同步复制:只有所有的 follower 把数据都复制之后才 Commit,这种策略的一致性好,但可用性不高,当 follower 数量较多时,复制过程就会很耗时。
  • 异步复制:只要 leader 拿到数据就立即 Commit,然后 follower 再复制,这种策略的可用性高,但一致性较差,例如在 Commit 之后 leader 挂掉,其他 follow 中就都没有该数据了。

  那么 Kafka 使用的是什么策略呢?Kafka 使用了一种 ISR (in-sync Replica)机制

  • leader 会维护一个与其基本保持同步的 Replica 列表,称为 ISR(in-sync Replica);
  • 每个 Partition 都会有一个 ISR ,而且是由 leader 动态维护;
  • 如果 ISR 中有一个 flower 比一个 leader 落后太多,或者超过一定时间没有请求复制数据,则将其移除;
  • 当 ISR 中所有 Replica 都向 leader 发送 ACK 时,leader 才会 Commit。

3.ACK 机制

  ACK:为了保证 Producer 发送的消息能够到达指定的 Topic,每个 Partition 收到消息之后要向 Producer 发送 ACK(acknowledgement)确认收到,如果 Producer 收到了 ACK,就会进行下一轮的发送,否则重新发送消息。

  对于某些不太重要的数据,对数据的完整性没有严格的要求,可以容忍少量数据的丢失,Kafka 就没有必要等 ISR 中的所有 follower 都复制完,所以 Kafka 提供了三种可靠性级别,供用户进行选择和配置:

  • 0:Producer 不用等待接收 ACK,只要数据接收到就返回,此时提供了最低的延迟,但若出现故障,会丢失数据;
  • 1:Producer 等待 ACK,leader 接收成功后发送 ACK,丢失数据会重发,但若 follower 同步前 leader 挂掉了,会丢失数据;
  • -1:Producer 等待 ACK,leader 接收到数据,follower 同步完数据后发送 ACK,但若 follower 同步完,而 ACK 还没发送 leader 就挂掉了,会出现数据重复。

三、Kafka 消费策略

1.消费者组 Consumer Group

  Consumer Group,消费者组,一个消费者组包含多个消费者,这些消费者共用一个 ID,即 Group ID,组内的消费者协调消费所订阅的主题的所有分区,当然了,每个分区只能由一个消费者进行消费。

2.偏移量 offset

  offset ,偏移量,记录的是消费位置信息,即在消费者消费数据的过程中,已经消费了多少数据。

  要获取 offset 的信息,需要知道消费者组的 ID 、主题和分区 ID。在老版本的 Kafka 中(0.9以前),offset 信息是保存在 ZooKeeper 中的,目录结构如下:

/consumers/<groupId>/offsets/<topic>/<partitionId>

  但在新版本中(0.9及其之后的版本),Kafka 增加了一个主题:__consumers_offsets,将 offset 信息写入这个 Topic。不过这个 Topic 默认是不使用的,若要使用需要修改相应的设置,需要在 consumer.properties 中设置:

exclude.internal.topics=false

  查询 __consumer_offsets Topic 中的所有内容,如果是0.11.0.0之前的版本,使用如下命令:

bin/kafka-console-consumer.sh --topic __consumer_offsets --zookeeper localhost:2181 --formatter "kafka.coordinator.GroupMetadataManager\$OffsetsMessageFormatter" --consumer.config config/consumer.properties --from-beginning

  如果是0.11.0.0及其之后的版本,使用如下命令:

bin/kafka-console-consumer.sh --topic __consumer_offsets --zookeeper localhost:2181 --formatter "kafka.coordinator.group.GroupMetadataManager\$OffsetsMessageFormatter" --consumer.config config/consumer.properties --from-beginning

3.消费策略

1)RangeAssignor

  Kafka 默认的消费策略。

  RangeAssignor 策略的原理是按照消费者总数和分区总数进行整除运算来获得一个跨度,然后将分区按照跨度进行平均分配,以保证分区尽可能均匀地分配给所有的消费者。对于每一个 Topic,RangeAssignor 策略会将消费组内所有订阅这个 Topic 的消费者按照名称的字典序排序,然后为每个消费者划分固定的分区范围,如果不够平均分配,那么字典序靠前的消费者会被多分配一个分区。

  假设消费组内有2个消费者 C1 和 C2,都订阅了主题 Topic1 和 Topic2,并且每个主题都有3个分区,那么所订阅的所有分区可以标识为:T10、T11、T12、T20、T21、T22。最终的分配结果为:

  

  可以看到这样分配已经不均了,如果将类似的情况扩大,可能出现超出部分消费者消费能力的情况。

2)RoundRobinAssignor

  RoundRobinAssignor 策略的原理是将消费组内所有消费者以及消费者所订阅的所有 Topic 的 Partition 按照字典序排序,然后通过轮询方式逐个将分区以此分配给每个消费者。

  假设有3个主题 Topic1、Topic2、Topic3,分别有1、2、3个分区,那么所订阅的所有分区可以标识为:T10、T20、T21、T30、T31、T32。消费组内有3个消费者 C1、C2、C3,其中 C1 订阅了 Topic1,C2 订阅了 Topic1 和 Topic2,C3 订阅了 Topic1、Topic2 和 Topic3。最终的分配结果为:

  

  可以看到该策略也不是十分完美,这样分配其实并不是最优解,因为完全可以将分区 T10 和 T11 分配给消费者 C1。

Kafka 入门(二)--数据日志、副本机制和消费策略的更多相关文章

  1. innodb二阶段日志提交机制和组提交解析

    前些天在查看关于innodb_flush_log_at_trx_commit的官网解释时产生了一些疑问,关于innodb_flush_log_at_trx_commit参数的详细解释参见官网: htt ...

  2. SpringBoot入门(二):日志及自定义属性

    这一章主要说springboot中日志的配置.自定义属性的配置与读取.分环境的yml配置文件(如本地环境.测试环境.生产环境等).比较偏向实际开发,较为实用,前面一章的一些基本创建在这里就不多废话了. ...

  3. 入门大数据---Kafka深入理解分区副本机制

    一.Kafka集群 Kafka 使用 Zookeeper 来维护集群成员 (brokers) 的信息.每个 broker 都有一个唯一标识 broker.id,用于标识自己在集群中的身份,可以在配置文 ...

  4. kafka副本机制之数据可靠性

    一.概述 为了提升集群的HA,Kafka从0.8版本开始引入了副本(Replica)机制,增加副本机制后,每个副本可以有多个副本,针对每个分区,都会从副本集(Assigned Replica,AR)中 ...

  5. 深入理解 Kafka 副本机制

    一.Kafka集群 二.副本机制         2.1 分区和副本         2.2 ISR机制         2.3 不完全的首领选举         2.4 最少同步副本         ...

  6. Kafka 学习之路(五)—— 深入理解Kafka副本机制

    一.Kafka集群 Kafka使用Zookeeper来维护集群成员(brokers)的信息.每个broker都有一个唯一标识broker.id,用于标识自己在集群中的身份,可以在配置文件server. ...

  7. Kafka 系列(五)—— 深入理解 Kafka 副本机制

    一.Kafka集群 Kafka 使用 Zookeeper 来维护集群成员 (brokers) 的信息.每个 broker 都有一个唯一标识 broker.id,用于标识自己在集群中的身份,可以在配置文 ...

  8. 入门大数据---基于Zookeeper搭建Kafka高可用集群

    一.Zookeeper集群搭建 为保证集群高可用,Zookeeper 集群的节点数最好是奇数,最少有三个节点,所以这里搭建一个三个节点的集群. 1.1 下载 & 解压 下载对应版本 Zooke ...

  9. (二)Kafka动态增加Topic的副本(Replication)

    (二)Kafka动态增加Topic的副本(Replication) 1. 查看topic的原来的副本分布 [hadoop@sdf-nimbus-perf ~]$ le-kafka-topics.sh ...

随机推荐

  1. Oracle 导入数据库dmp文件

    场景:windows2008 R2系统 ,往新安装的oracle11g数据库导入同事给的dmp文件到指定的新建的用户. 1.创建表空间 在导入dmp文件之前,先打开查看dmp文件的表空间名称(tabl ...

  2. egret canvas的style

    <canvas width="1920" height="1080" style=" cursor:auto;//鼠标样式 positon:ob ...

  3. egret的WebView实现

    需求 在egret中嵌入网页,类似 . 网上大概有两种思路吧,一种是直接在body里面加入iframe,如:[Egret]里使用iframe标签达到内嵌多个web界面;另一种就是通过模仿htmlinp ...

  4. 如何在项目开发中应用好“Deadline 是第一生产力”?

    我想也许你早就听说过"Deadline是第一生产力"这句话,哪怕以前没听说过,我相信看完本文后,再也不会忘记这句话,甚至时不时还要感慨一句:"Deadline是第一生产力 ...

  5. YoyoGo基于ASP.NET Core设计的Golang实现

    YoyoGo YoyoGo 是一个用 Go 编写的简单,轻便,快速的 微服务框架,目前已实现了Web框架的能力,但是底层设计已支持. Github https://github.com/yoyofx/ ...

  6. 【贪心】Emergency Evacuation

    题目 大致题意 把指定的人从同一出口送出车外,且同一位置不能同时有两个人,求所需的最短时间. 分析 第一感觉就是利用贪心思想解决问题,但是这道题的数据范围用模拟的话肯定是会爆掉的,所以这是不可取的.我 ...

  7. 为DLL文件添加强名称

    程序在编译时出现类似 "错误 1 程序集生成失败 -- 引用的程序集“XXXXXXXXXX”没有强名称" 这样的错误,是因为它不是强名称的,则需要进行以下操作: 例如:com.so ...

  8. visual studio 项目中使用EF创建的数据库,后续更新数据库操作(生产已经部署,不能删除数据库重新创建)

    情景:SharePoint项目(其他类型的项目道理也一样),数据库是用EF(版本:6.0.0.0)创建的,生产环境已经使用,所以后续修改数据库,只能通过更新来实现. 下面是具体的操作方式: 1.vis ...

  9. JVM源码分析之Object.wait/notify实现

    ​ “365篇原创计划”第十一篇.   今天呢!灯塔君跟大家讲:   JVM源码分析之Object.wait/notify实现       最简单的东西,往往包含了最复杂的实现,因为需要为上层的存在提 ...

  10. css定位方式有哪几种?

    复杂的网页布局都是通过各种网页元素灵活定位实现的,网页中的各种元素定位都有自己的特点.下面我们来看一下css的几种定位方式. float定位(即浮动定位): 这种定位方式很简单,只需规定一个浮动的方向 ...