kafka再浅析

在日常开发中,经常使用kafka,对它是既熟悉又陌生,下面继续聊,继续总结。
1、消息中间件
分布式消息是一种通信机制,和RPC、HTTP不一样,消息中间件采用分布式中间代理的方式进行通信。采用消息中间件后,上游业务系统发送消息,消息先存储在消息中间件,然后由消息中间件将消息分发到对应的下游业务系统,这种异步的方式减少了服务之间的耦合程度。
在系统架构中引用额外的组件,必然提高系统的架构复杂度和运行的难度,那么消息中间件又带来了哪些优势呢?

  • 解耦
  • 冗余
  • 扩展性
  • 削峰
  • 顺序性
  • 异步通信

2、kafka基本概念
在这里插入图片描述
(摘自网上)

  • producer:生产者,也就是发送消息的一方。生产者负责创建消息,然后将其发送到 Kafka;
  • consumer:消费者,也就是接受消息的一方。消费者连接到 Kafka 上并接收消息,进而进行相应的业务逻辑处理;
  • consumer group:一个消费者组可以包含一个或多个消费者。使用多分区 + 多消费者方式可以极大提高数据下游的处理速度,同一消费组中的消费者不会重复消费消息,同样的,不同消费组中的消费者消费消息时互不影响。Kafka 就是通过消费组的方式来实现消息 P2P 模式和广播模式;
  • broker:服务代理节点。Broker 是 Kafka 的服务节点,即 Kafka 的服务器;
  • topic:Kafka 中的消息以 Topic 为单位进行划分,生产者将消息发送到特定的 Topic,而消费者负责订阅 Topic 的消息并进行消费;
  • partition:Topic 是一个逻辑的概念,它可以细分为多个分区,每个分区只属于单个主题。同一个主题下不同分区包含的消息是不同的,分区在存储层面可以看作一个可追加的日志(Log)文件,消息在被追加到分区日志文件的时候都会分配一个特定的偏移量(offset);
  • offset:offset 是消息在分区中的唯一标识,Kafka 通过它来保证消息在分区内的顺序性,不过 offset 并不跨越分区,也就是说,Kafka 保证的是分区有序性而不是主题有序性;
  • replication:副本,是 Kafka 保证数据高可用的方式,Kafka 同一 Partition 的数据可以在多 Broker 上存在多个副本,通常只有主副本对外提供读写服务,当主副本所在 broker 崩溃或发生网络异常,Kafka 会在 Controller 的管理下会重新选择新的 Leader 副本对外提供读写服务;
  • record:实际写入 Kafka 中并可以被读取的消息记录。每个 record 包含了 key、value 和 timestamp;

自问自答:

  • 简单讲下 Kafka 的架构?
    答:Producer、Consumer、Consumer Group、Topic、Partition
  • Kafka 是推模式还是拉模式,推拉的区别是什么?
    答:Kafka Producer 向 Broker 发送消息使用 Push 模式,Consumer 消费采用的 Pull 模式。拉取模式,让 consumer 自己管理 offset,可以提供读取性能。
  • Kafka 如何广播消息?
    答:Consumer group
  • Kafka 的消息是否是有序的?
    答:Topic 级别无序,Partition 有序;
  • Kafka 是否支持读写分离?
    答:不支持,只有 Leader 对外提供读写服务;
  • Kafka 如何保证数据高可用?
    答:副本,ack,HW
  • Kafka 中 zookeeper 的作用?
    答:集群管理,元数据管理

3、kafka命令行工具
Kafka 的命令行工具在 Kafka 包的/bin目录下,主要包括服务和集群管理脚本,配置脚本,信息查看脚本,Topic 脚本,客户端脚本等。

  • kafka-configs.sh:配置管理脚本
  • kafka-console-consumer.sh:kafka 消费者控制台
  • kafka-console-producer.sh:kafka 生产者控制台
  • kafka-consumer-groups.sh:kafka 消费者组相关信息
  • kafka-delete-records.sh:删除低水位的日志文件
  • kafka-log-dirs.sh:kafka 消息日志目录信息
  • kafka-mirror-maker.sh:不同数据中心 kafka 集群复制工具
  • kafka-preferred-replica-election.sh:触发 preferred replica 选举
  • kafka-producer-perf-test.sh:kafka 生产者性能测试脚本
  • kafka-reassign-partitions.sh:分区重分配脚本
  • kafka-replica-verification.sh:复制进度验证脚本
  • kafka-server-start.sh:启动 kafka 服务
  • kafka-server-stop.sh:停止 kafka 服务
  • kafka-topics.sh:topic 管理脚本
  • kafka-verifiable-consumer.sh:可检验的 kafka 消费者
  • kafka-verifiable-producer.sh:可检验的 kafka 生产者
  • zookeeper-server-start.sh:启动 zk 服务
  • zookeeper-server-stop.sh:停止 zk 服务
  • zookeeper-shell.sh:zk 客户端

通常可以使用kafka-console-consumer.sh和kafka-console-producer.sh脚本来测试 Kafka 生产和消费,kafka-consumer-groups.sh可以查看和管理集群中的 Topic,kafka-topics.sh通常用于查看 Kafka 的消费组情况。

4、kafka producer
Kafka producer 的正常生产逻辑包含以下几个步骤:

  1. 配置生产者客户端参数;
  2. 构建待发送的消息;
  3. 发送消息;
  4. 关闭生产者实例;

producer发送消息的过程如下,需要经过拦截器、序列化器和分区器,最终由累加器批量发送至broker。
在这里插入图片描述
(摘自网上)
kafka producer参数:

  • bootstrap.server:指定 Kafka 的 Broker 的地址;
  • key.serializer:key 序列化器;
  • value.serializer:value 序列化器;
  • batch.num.messages:默认值:200,每次批量消息的数量,只对 asyc 起作用;
  • request.required.acks:默认值:0,0 表示 producer 毋须等待 leader 的确认,1 代表需要 leader 确认写入它的本地 log 并立即确认,-1 代表所有的备份都完成后确认。只对 async 模式起作用,这个参数的调整是数据不丢失和发送效率的 tradeoff,如果对数据丢失不敏感而在乎效率的场景可以考虑设置为 0,这样可以大大提高 producer 发送数据的效率;
  • request.timeout.ms:默认值:10000,确认超时时间;
  • partitioner.class:默认值:kafka.producer.DefaultPartitioner,必须实现 kafka.producer.Partitioner,根据 Key 提供一个分区策略。有时候我们需要相同类型的消息必须顺序处理,这样我们就必须自定义分配策略,从而将相同类型的数据分配到同一个分区中;
  • producer.type:默认值:sync,指定消息发送是同步还是异步。异步 asyc 成批发送用 kafka.producer.AyncProducer, 同步 sync 用 kafka.producer.SyncProducer。同步和异步发送也会影响消息生产的效率;
  • compression.topic:默认值:none,消息压缩,默认不压缩。其余压缩方式还有,“gzip”、“snappy"和"lz4”。对消息的压缩可以极大地减少网络传输量、降低网络 IO,从而提高整体性能;
  • compressed.topics:默认值:null,在设置了压缩的情况下,可以指定特定的 topic 压缩,未指定则全部压缩;
  • message.send.max.retries:默认值:3,消息发送最大尝试次数;
  • retry.backoff.ms:默认值:300,每次尝试增加的额外的间隔时间;
  • topic.metadata.refresh.interval.ms:默认值:600000,定期的获取元数据的时间。当分区丢失,leader 不可用时 producer 也会主动获取元数据,如果为 0,则每次发送完消息就获取元数据,不推荐。如果为负值,则只有在失败的情况下获取元数据;
  • queue.buffering.max.ms:默认值:5000,在 producer queue 的缓存的数据最大时间,仅仅 for asyc;
  • queue.buffering.max.message:默认值:10000,producer 缓存的消息的最大数量,仅仅 for asyc;
  • queue.enqueue.timeout.ms:默认值:-1,0 当 queue 满时丢掉,负值是 queue 满时 block, 正值是 queue 满时 block 相应的时间,仅仅 for asyc;

5、kafka comsumer
Kafka 有消费组的概念,每个消费者只能消费所分配到的分区的消息,每一个分区只能被一个消费组中的一个消费者所消费,所以同一个消费组中消费者的数量如果超过了分区的数量,将会出现有些消费者分配不到消费的分区。
Kafka Consumer Client 消费消息通常包含以下步骤:

  1. 配置客户端,创建消费者;
  2. 订阅主题;
  3. 拉取消息并消费;
  4. 提交消费位移;
  5. 关闭消费者实例;

因为 Kafka 的 Consumer 客户端是线程不安全的,为了保证线程安全,并提升消费性能,可以在 Consumer 端采用类似 Reactor 的线程模型来消费数据。
在这里插入图片描述
(摘自网上)
kafka consumer参数:

  • bootstrap.servers:连接 broker 地址,host:port 格式;
  • group.id:消费者隶属的消费组;
  • key.deserializer:与生产者的key.serializer对应,key 的反序列化方式;
  • value.deserializer:与生产者的value.serializer对应,value 的反序列化方式;
  • session.timeout.ms:coordinator 检测失败的时间。默认 10s 该参数是 Consumer Group 主动检测 (组内成员 comsummer) 崩溃的时间间隔,类似于心跳过期时间;
  • 默认值是 latest,也就是从最新记录读取数据(消费者启动之后生成的记录),另一个值是 earliest,意思是在偏移量无效的情况下,消费者从起始位置开始读取数据;
  • enable.auto.commit:否自动提交位移,如果为false,则需要在程序中手动提交位移。对于精确到一次的语义,最好手动提交位移;
  • fetch.max.bytes:单次拉取数据的最大字节数量;
  • max.poll.records:单次 poll 调用返回的最大消息数,如果处理逻辑很轻量,可以适当提高该值。但是max.poll.records条数据需要在 session.timeout.ms 这个时间内处理完 。默认值为 500;
  • request.timeout.ms:一次请求响应的最长等待时间。如果在超时时间内未得到响应,kafka 要么重发这条消息,要么超过重试次数的情况下直接置为失败;

6、kafka rebalance
rebalance 本质上是一种协议,规定了一个 consumer group 下的所有 consumer 如何达成一致来分配订阅 topic 的每个分区。比如某个 group 下有 20 个 consumer,它订阅了一个具有 100 个分区的 topic。正常情况下,Kafka 平均会为每个 consumer 分配 5 个分区。这个分配的过程就叫 rebalance。
rebalance 的触发条件有三种:

  • 组成员发生变更(新 consumer 加入组、已有 consumer 主动离开组或已有 consumer 崩溃了)
  • 订阅主题数发生变更
  • 订阅主题的分区数发生变更

Kafka 默认提供了两种分配策略:

  • Range
  • Round-Robin

7、kafka高可用
在分布式数据系统中,通常使用分区来提高系统的处理能力,通过副本来保证数据的高可用性。多分区意味着并发处理的能力,这多个副本中,只有一个是 leader,而其他的都是 follower 。仅有 leader 副本可以对外提供服务。多个 follower 副本通常存放在和 leader 副本不同的 broker 中。通过这样的机制实现了高可用,当某台机器挂掉后,其他 follower 副本也能迅速”转正“,开始对外提供服务。
follower 副本不提供读服务,试想一下,如果 follower 副本也对外提供服务那会怎么样呢?首先,性能是肯定会有所提升的。但同时,会出现一系列问题。类似数据库事务中的幻读,脏读。比如你现在写入一条数据到 kafka 主题 a,消费者 b 从主题 a 消费数据,却发现消费不到,因为消费者 b 去读取的那个分区副本中,最新消息还没写入。而这个时候,另一个消费者 c 却可以消费到最新那条数据,因为它消费了 leader 副本。Kafka 通过 WH 和 Offset 的管理来决定 Consumer 可以消费哪些数据,已经当前写入的数据。
只有 Leader 可以对外提供读服务,那如何选举 Leader。kafka 会将与 leader 副本保持同步的副本放到 ISR 副本集合中。当然,leader 副本是一直存在于 ISR 副本集合中的,在某些特殊情况下,ISR 副本中甚至只有 leader 一个副本。当 leader 挂掉时,kakfa 通过 zookeeper 感知到这一情况,在 ISR 副本中选取新的副本成为 leader,对外提供服务。但这样还有一个问题,前面提到过,有可能 ISR 副本集合中,只有 leader,当 leader 副本挂掉后,ISR 集合就为空,这时候怎么办呢?这时候如果设置 unclean.leader.election.enable 参数为 true,那么 kafka 会在非同步,也就是不在 ISR 副本集合中的副本中,选取出副本成为 leader。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值