Kafka核心技术与实战 <一>

816 阅读11分钟

其他更多java基础文章:
java基础学习(目录)


这系列是根据极客时间《Kafka核心技术与实战》这个课程做的笔记

本篇目录

  • Kafka术语
  • Kafa版本演进
  • 上线部署
  • 集群重点参数

Kafka术语

  • 消息:Record。 Kafka 是消息引擎嘛,这里的消息就是指 Kafka 处理的主要对象。主题:Topic。主题是承载消息的逻辑容器,在实际使用中多用来区分具体的业务。
  • 分区:Partition。 一个有序不变的消息序列。每个主题下可以有多个分区。
  • 消息位移:Offset。 表示分区中每条消息的位置信息,是一个单调递增且不变的值。副本:Replica。Kafka 中同一条消息能够被拷贝到多个地方以提供数据冗余,这些地方就是所谓的副本。副本还分为领导者副本和追随者副本,各自有不同的角色划分。副本是在分区层级下的,即每个分区可配置多个副本实现高可用。
  • 生产者:Producer。 向主题发布新消息的应用程序。
  • 消费者:Consumer。 从主题订阅新消息的应用程序。
  • 消费者位移:Consumer Offset。 表征消费者消费进度,每个消费者都有自己的消费者位移。
  • 消费者组:Consumer Group。 多个消费者实例共同组成的一个组,同时消费多个分区以实现高吞吐。
  • Broker :Kafka 的服务器端由被称为 Broker 的服务进程构成,即一个 Kafka 集群由多个 Broker 组成,Broker 负责接收和处理客户端发送过来的请求,以及对消息进行持久化。
  • 重平衡:Rebalance。 消费者组内某个消费者实例挂掉后,其他消费者实例自动重新分配订阅主题分区的过程。Rebalance 是 Kafka 消费者端实现高可用的重要手段。

Kafa版本演进

  • Kafka 目前总共演进了 7 个大版本,分别是 0.7、0.8、0.9、0.10、0.11、1.0 和 2.0,
  • Kafka 从 0.7 时代演进到 0.8 之后正式引入了副本机制,
  • 0.8.2.0 版本社区引入了新版本 Producer API,即需要指定 Broker 地址的 Producer。我的建议是尽量使用比较新 的版本。如果你不能升级大版本,我也建议你至少要升级到 0.8.2.2 这个版本,因为该版本 中老版本消费者 API 是比较稳定的。另外即使你升到了 0.8.2.2,也不要使用新版本 Producer API,此时它的 Bug 还非常多
  • 0.9.0.0 是新版本 Producer API 在这个版本中算比较稳定了。
  • 0.10.0.0 是里程碑式的大版本,因为该版本引入了 Kafka Streams。。如果你依 然在使用 0.10 大版本,我强烈建议你至少升级到 0.10.2.2 然后使用新版本 Consumer API。还有个事情不得不提,0.10.2.2 修复了一个可能导致 Producer 性能降低的 Bug。 基于性能的缘故你也应该升级到 0.10.2.2。
  • 在 2017 年 6 月,社区发布了 0.11.0.0 版本,引入了两个重量级的功能变更:一个是提供 幂等性 Producer API 以及事务(Transaction) API;另一个是对 Kafka 消息格式做了重 构。如果你对 1.0 版本是否适用于线上环境依然感到困惑,那么至少将你的环境升级到 0.11.0.3,因为这个版本的消息引擎功能已经非常完善了。
  • 1.0 和 2.0 版本吧,因为在我看来这两个大版本主要还是 Kafka Streams 的各种改进,在消息引擎方面并未引入太多的重大功能特性。

上线部署

集群重点参数

类型 参数名 描述 备注
Broker log.dirs 这是非常重要的参数,指定了 Broker 需要 使用的若干个文件目录路径。 这两个参数应该怎么设置呢?很简单,你只要设置 log.dirs,即第一个参数就好了,不要设置log.dir。而 且更重要的是,在线上生产环境中一定要为log.dirs配置 多个路径,具体格式是一个 CSV 格式,也就是用逗号分隔 的多个路径,比 如/home/kafka1,/home/kafka2,/home/kafka3这 样。如果有条件的话你最好保证这些目录挂载到不同的物理 磁盘上。这样做有两个好处:
log.dir 注意这是 dir,结尾没有 s,说明它只能表示 单个路径,它是补充上一个参数用的。 1.提升读写性能:比起单块磁盘,多块物理磁盘同时读写数 据有更高的吞吐量。

2.能够实现故障转移:即 Failover。这是 Kafka 1.1 版本新 引入的强大功能。要知道在以前,只要 Kafka Broker 使 用的任何一块磁盘挂掉了,整个 Broker 进程都会关闭。 但是自 1.1 开始,这种情况被修正了,坏掉的磁盘上的数 据会自动地转移到其他正常的磁盘上,而且 Broker 还能 正常工作。还记得上一期我们关于 Kafka 是否需要使用 RAID 的讨论吗?这个改进正是我们舍弃 RAID 方案的基 础:没有这种 Failover 的话,我们只能依靠 RAID 来提 供保障。

zookeeper.connect 可以指定它的值为 zk1:2181,zk2:2181,zk3:2181 如果我让多个 Kafka 集群使用同一套 ZooKeeper 集群,那么这个参数应该怎么设置呢?这时候 chroot 就派上用场了。这个 chroot 是 ZooKeeper 的概 念,类似于别名。

如果你有两套 Kafka 集群,假设分别叫它们 kafka1 和 kafka2,那么两套集群的zookeeper.connect参数可以 这样指定:zk1:2181,zk2:2181,zk3:2181/kafka1和 zk1:2181,zk2:2181,zk3:2181/kafka2。

listeners监听器,其实就是告诉外部连接者 要通过什么协议访问指定主机名和端口开放的 Kafka 服 务。我们具体说说监听器的概念,从构成上来说,它是若干个逗 号分隔的三元组,每个三元组的格式为<协议名称,主机 名,端口号>。这里的协议名称可能是标准的名字,比如 PLAINTEXT 表示明文传输、SSL 表示使用 SSL 或 TLS 加密 传输等;也可能是你自己定义的协议名字,比如 CONTROLLER: //localhost:9092。
advertised.listeners和 listeners 相比多了个 advertised。Advertised 的含义表示宣称的、公布的, 就是说这组监听器是 Broker 用于对外发布的。经常有人会问主机 名这个设置中我到底使用 IP 地址还是主机名。这里我给出 统一的建议:最好全部使用主机名,即 Broker 端和 Client 端应用配置中全部填写主机名。 Broker 源代码中也使用的 是主机名,如果你在某些地方使用了 IP 地址进行连接,可 能会发生无法连接的问题。

advertised.listeners主要是为外网访问用的。如 果clients在内网环境访问Kafka不需要配置这个参数。

host.name/port压根不要为它们指定值,毕竟都是过期的参数 了。
listener.security.protocol.map一旦你自己定义了协议名称,你必须还要指定 listener.security.protocol.map参数告诉这个协议底层使用了哪种安全协议,比如指定 listener.security.protocol.map=CONTROLLER:P LAINTEXT表示CONTROLLER这个自定义协议底层使用明文 不加密传输数据。
auto.create.topics.enable是否允许自动创建 Topic。我建议最好设置成 false,即不允许自动创建 Topic。在我们的线上环境里面有 很多名字稀奇古怪的 Topic,我想大概都是因为该参数被设置成了 true 的缘故。
unclean.leader.election.enable是否允许 Unclean Leader 选举。只有保存数据比较多的那些副本才有资格竞选,那些落后进度太多的副本没资格竞争 Leader 。假设那些保存数据比较多的副本都挂了怎么办?

如果设置成 false,那么就坚持之前的原则,坚决不能让那 些落后太多的副本竞选 Leader。这样做的后果是这个分区就不可用了,因为没有 Leader 了。反之如果是 true,那么 Kafka 允许你从那些“跑得慢”的副本中选一个出来当 Leader。鉴于我不知道你用的是哪个版本的Kafka,所以建议你还是显式地把它设置成 false 吧。

auto.leader.rebalance.enable是否允许定期进 行 Leader 选举。设置它的值 为 true 表示允许 Kafka 定期地对一些 Topic 分区进行 Leader 重选举,当然这个重选举不是无脑进行的,它要满足一定的条件才会发生。严格来说它与上一个参数中Leader 选举的最大不同在于,它不是选 Leader,而是换 Leader!我建议你在生产环境中把这个参数设置成 false。
log.retention.{hour|minutes|ms}这是个“三 兄弟”,都是控制一条消息数据被保存多长时间。从优先 级上来说 ms 设置最高、minutes 次之、hour 最低。虽然 ms 设置有最高的优先级,但是 通常情况下我们还是设置 hour 级别的多一些,比如 log.retention.hour=168表示默认保存 7 天的数据
log.retention.bytes这是指定 Broker 为消息保存 的总磁盘容量大小。这个值默认是 -1, 表明你想在这台 Broker 上保存多少数据都可以
message.max.bytes控制 Broker 能够接收的最大消 息大小。默认的 1000012 太少了,还不到 1MB。实际场景中突 破 1MB 的消息都是屡见不鲜的,因此在线上环境中设置一 个比较大的值还是比较保险的做法。毕竟它只是一个标尺而 已,仅仅衡量 Broker 能够处理的最大消息大小,即使设置 大一点也不会耗费什么磁盘空间的。
Topicretention.ms规定了该 Topic 消息被保存的时长。 默认是 7 天,即该 Topic 只保存最近 7 天的消息。一旦 设置了这个值,它会覆盖掉 Broker 端的全局参数值。
retention.bytes规定了要为该 Topic 预留多大的磁 盘空间。和全局参数作用相似,这个值通常在多租户的 Kafka 集群中会有用武之地。当前默认值是 -1,表示可以 无限使用磁盘空间。
max.message.bytes它决定了 Kafka Broker 能够正常 接收该 Topic 的最大消息大小。
创建Topic时设置语句bin/kafka-topics.sh--bootstrap-server localhost:9092--create--topic transaction--partitions1 --replication-factor1 --config retention.ms=15552000000--config max.message.bytes=5242880
修改Topic时设置语句 bin/kafka-configs.sh--zookeeper localhost:2181--entity-typetopics --entity-name transaction--alter--add-config max.message.bytes=10485760
JVMKAFKA_HEAP_OPTS指定堆大小将你的 JVM 堆大小设置成 6GB 吧, 这是目前业界比较公认的一个合理值。
KAFKA_JVM_PERFORMANCE_OPTS指定 GC 参数如果你已经在使用 Java 8 了,那么使用 G1 收集器就好了。在没有任何调优的情况下,G1 表现得要比 CMS 出色。G1是jdk9中默认的,jdk8还是需要显式指定的
操作系统参数ulimit -n文件描述符限制通常情况下将它设置成一个超大的值是合理的做法,比如 ulimit -n 1000000。
文件系统类型这里所说的文件系统指的是如 ext3、ext4 或 XFS 这样的日志型文件系统。根据官网的测 试报告,XFS 的性能要强于 ext4,所以生产环境最好还是使用 XFS
swap 的调优网上很多文章都提到设置其为 0,将 swap 完全禁掉以防止 Kafka 进程使用 swap 空间。我个人 反倒觉得还是不要设置成 0 比较好,我们可以设置成一个较 小的值。为什么呢?因为一旦设置成 0,当物理内存耗尽 时,操作系统会触发 OOM killer 这个组件,它会随机挑选 一个进程然后 kill 掉,即根本不给用户任何的预警。但如果 设置成一个比较小的值,当开始使用 swap 空间时,你至少 能够观测到 Broker 性能开始出现急剧下降,从而给你进一 步调优和诊断问题的时间。基于这个考虑,我个人建议将 swappniess 配置成一个接近 0 但不为 0 的值,比如 1。
Flush 落盘时间向 Kafka 发送 数据并不是真要等数据被写入磁盘才会认为成功,而是只要 数据被写入到操作系统的页缓存(Page Cache)上就可以 了,随后操作系统根据 LRU 算法会定期将页缓存上 的“脏”数据落盘到物理磁盘上。这个定期就是由提交时间 来确定的,默认是 5 秒。一般情况下我们会认为这个时间太 频繁了,可以适当地增加提交间隔来降低物理磁盘的写操 作。