Kafka 起初是 由 LinkedIn 公司采用 Scala 语言开发的一个多分区、多副本且基于 ZooKeeper 协调的分布式消息系统,现已被捐献给 Apache 基金会。
目前 Kafka 已经定位为一个分布式流式处理平台,它以高吞吐、可持久化、可水平扩展、支持流数据处理等多种特性而被广泛使用,主要是由 Scala 和 Java 编写。
它是一种高吞吐量的分布式发布订阅消息系统,可以处理事件流数据。通过 Kafka 你可以非常方便的把想要发布的消息,分发给任何想要订阅该消息的接收者。上游生产者只需要把消息输入到 Kafka 指定 Topic ,下游接收者只要订阅该 Topic ,就能低延时、高吞吐量的接收到上游的消息;Kafka 还支持 同一个 Topic 同时被多个下游消费者消费,且不同消费者之间数据处理进度互不干扰。
目前越来越多的开源分布式处理系统如 Cloudera、Storm、Spark、Flink 等都支持与 Kafka 集成,Kafka 之所以受到越来越多的青睐,与它所“扮演”的三大角色是分不开的:
消息队列一般主要处理:异步处理、服务解耦、流量控制,因此 Kafka 作为消息队列的一种,同样在解决这些问题。
Producer:消息生产者,也就是发送消息的一方。生产者负责创建消息,然后将其投递到 Kafka 中;
Consumer:消息消费者,也就是接收消息的一方。消费者连接到 Kafka 上并接收消息,进而进行相应的业务逻辑处理;
Consumer Group (CG):消费者组,由多个 consumer 组成。消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个组内消费者消费;消费者组之间互不影响。所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者。
Broker:服务代理节点。对于 Kafka 而言,Broker 可以简单地看作一个独立的 Kafka 服务节点或 Kafka 服务实例。大多数情况下也可以将 Broker 看作一台 Kafka 服务器,前提是这台服务器上只部署了一个 Kafka 实例。一个或多个 Broker 组成了一个 Kafka 集群。一般而言,我们更习惯使用首字母小写的 broker 来表示服务代理节点。
Controller:集群中会有一个或者多个 broker,其中有一个 broker 会被选举为控制器(Kafka Controller),它负责管理整个集群中所有分区和副本的状态。
在 Kafka 中还有两个特别重要的概念—主题(Topic)与分区(Partition)
Topic:
可以理解为一个队列,生产者和消费者在队列的两端,一个输出数据,一个消费数据,它们面向的都是一个 topic;
Partition:
为了实现扩展性,一个数据量非常大的 topic 可以分布到多个 broker(即服务器)上,一个 topic 可以分为多个 partition,每个 partition 是一个有序的队列;那么 topic 的并发度基本等于 partition 的个数。
Kafka 中的消息以主题为单位进行归类,生产者负责将消息发送到特定的主题(发送到 Kafka 集群中的每一条消息都要指定一个主题),而消费者负责订阅主题并进行消费。
主题是一个逻辑上的概念,它还可以细分为多个分区,一个分区只属于单个主题,很多时候也会把分区称为主题分区(Topic-Partition)。同一主题下的不同分区包含的消息是不同的,分区在存储层面可以看作一个可追加的日志(Log)文件,消息在被追加到分区日志文件的时候都会分配一个特定的偏移量(offset)。
offset 是消息在分区中的唯一标识,Kafka 通过它来保证消息在分区内的顺序性,不过 offset 并不跨越分区,也就是说,Kafka 保证的是分区有序而不是主题有序。
如上图所示:主题中有 4 个分区,消息被顺序追加到每个分区日志文件的尾部。Kafka 中的分区可以分布在不同的服务器(broker)上,也就是说,一个主题可以横跨多个 broker,以此来提供比单个 broker 更强大的性能。
每一条消息被发送到 broker 之前,会根据分区规则选择存储到哪个具体的分区。如果分区规则设定得合理,所有的消息都可以均匀地分配到不同的分区中。如果一个主题只对应一个文件,那么这个文件所在的机器 I/O 将会成为这个主题的性能瓶颈,而分区解决了这个问题。在创建主题的时候可以通过指定的参数来设置分区的个数,当然也可以在主题创建完成之后去修改分区的数量,通过增加分区的数量可以实现水平扩展。
Replica:
Kafka 为分区引入了多副本(Replica)机制,通过增加副本数量可以提升容灾能力。
同一分区的不同副本中保存的是相同的消息(在同一时刻,副本之间并非完全一样),副本之间是“一主多从”的关系,其中 leader 副本负责处理读写请求,follower 副本只负责与 leader 副本的消息同步。副本处于不同的 broker 中,当 leader 副本出现故障时,从 follower 副本中重新选举新的 leader 副本对外提供服务。Kafka 通过多副本机制实现了故障的自动转移,当 Kafka 集群中某个 broker 失效时仍然能保证服务可用。
如上图所示:Kafka 集群中有 4 个 broker,某个主题中有 3 个分区,且副本因子(即副本个数)也为 3,如此每个分区便有 1 个 leader 副本和 2 个 follower 副本。生产者和消费者只与 leader 副本进行交互,而 follower 副本只负责消息的同步,很多时候 follower 副本中的消息相对 leader 副本而言会有一定的滞后。
Kafka 消费端也具备一定的容灾能力。Consumer 使用拉(Pull)模式从服务端拉取消息,并且保存消费的具体位置,当消费者宕机后恢复上线时可以根据之前保存的消费位置重新拉取需要的消息进行消费,这样就不会造成消息丢失。
更多:想了解更多关于:大数据运维相关的系统环境准备、基础环境安装、集群部署以及应用组件安装等全方位的技术的问题。如:从环境搭建/集群部署,内存扩容/问题排查,数据迁移等问题都可以来找我
Kafka 的命令行工具路径:xxx/kafka/bin/下
可以管理 Topic ,包括 创建、删除、分区扩容、查询 Topic 详细信息、查看 Topic 列表 等
命令工具:kafka-topics.sh
# 创建 Topic:
kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 3 --partitions 3 --topic test
# Topic 分区扩容
kafka-topics.sh --zookeeper localhost:2181 --alter --topic test --partitions 4
# 删除 Topic:
kafka-topics.sh --delete --zookeeper localhost:2181 localhost:9092 --topic test
#查询 Topic 详细信息
[DEV (v.v) sa_cluster@hybrid03 bin]$ ./kafka-topics.sh --topic event_topic --zookeeper localhost:2181 --describe
Topic:event_topic PartitionCount:10 ReplicationFactor:2 Configs:compression.type=gzip
Topic: event_topic Partition: 0 Leader: 1001 Replicas: 1001,1003 Isr: 1001,1003
Topic: event_topic Partition: 1 Leader: 1003 Replicas: 1003,1002 Isr: 1003,1002
Topic: event_topic Partition: 2 Leader: 1002 Replicas: 1002,1001 Isr: 1002,1001
Topic: event_topic Partition: 3 Leader: 1001 Replicas: 1001,1002 Isr: 1001,1002
Topic: event_topic Partition: 4 Leader: 1003 Replicas: 1003,1001 Isr: 1003,1001
Topic: event_topic Partition: 5 Leader: 1002 Replicas: 1002,1003 Isr: 1002,1003
Topic: event_topic Partition: 6 Leader: 1001 Replicas: 1001,1003 Isr: 1001,1003
Topic: event_topic Partition: 7 Leader: 1003 Replicas: 1003,1002 Isr: 1003,1002
Topic: event_topic Partition: 8 Leader: 1002 Replicas: 1002,1001 Isr: 1002,1001
Topic: event_topic Partition: 9 Leader: 1001 Replicas: 1001,1002 Isr: 1001,1002
#列出全部 Topic
kafka-topics.sh --bootstrap-server xxxxxx:9092 --list --exclude-internal
增删节点后的数据均衡
增加数据节点后,虽然新节点上已经启动了 broker ,但 kafka 不会自动均衡数据,需要手动执行。
命令工具:kafka-reassign-partitions.sh
更多:想了解更多关于:大数据运维相关的系统环境准备、基础环境安装、集群部署以及应用组件安装等全方位的技术的问题。如:从环境搭建/集群部署,内存扩容/问题排查,数据迁移等问题都可以来找我
编写配置文件 move-json-file.json ,告诉 kafka 你希望哪些 topic 要重新分区:
{
"topics": [{
"topic": "event_topic"
},
{
"topic": "profile_topic"
},
{
"topic": "item_topic"
}
],
"version": 1
}
执行命令生成分配信息:要注意的是,此时分区移动尚未开始,它只是告诉你当前的分配和建议。保存当前分配,以防你想要回滚它。
# 下面 --broker-list 参数 对应的是 brokerid
[DEV (v.v) cluster@hybrid03 bin]$ ./kafka-reassign-partitions.sh --zookeeper localhost:2181 --topics-to-move-json-file ~/mv.json --broker-list "1001,1002" --generate
Current partition replica assignment #当前分配信息
{"version":1,"partitions":[{"topic":"event_topic","partition":2,"replicas":[1002,1001],"log_dirs":["any","any"]},{"topic":"event_topic","partition":8,"replicas":[1002,1001],"log_dirs":["any","any"]},{"topic":"event_topic","partition":3,"replicas":[1001,1002],"log_dirs":["any","any"]},{"topic":"event_topic","partition":6,"replicas":[1001,1003],"log_dirs":["any","any"]},{"topic":"event_topic","partition":9,"replicas":[1001,1002],"log_dirs":["any","any"]},{"topic":"item_topic","partition":0,"replicas":[1001,1003],"log_dirs":["any","any"]},{"topic":"event_topic","partition":0,"replicas":[1001,1003],"log_dirs":["any","any"]},{"topic":"event_topic","partition":5,"replicas":[1002,1003],"log_dirs":["any","any"]},{"topic":"profile_topic","partition":2,"replicas":[1001,1003],"log_dirs":["any","any"]},{"topic":"profile_topic","partition":1,"replicas":[1002,1001],"log_dirs":["any","any"]},{"topic":"event_topic","partition":4,"replicas":[1003,1001],"log_dirs":["any","any"]},{"topic":"event_topic","partition":1,"replicas":[1003,1002],"log_dirs":["any","any"]},{"topic":"event_topic","partition":7,"replicas":[1003,1002],"log_dirs":["any","any"]},{"topic":"profile_topic","partition":0,"replicas":[1003,1002],"log_dirs":["any","any"]}]}
Proposed partition reassignment configuration #分配后的信息
{"version":1,"partitions":[{"topic":"event_topic","partition":7,"replicas":[1002,1001],"log_dirs":["any","any"]},{"topic":"profile_topic","partition":1,"replicas":[1002,1001],"log_dirs":["any","any"]},{"topic":"event_topic","partition":1,"replicas":[1002,1001],"log_dirs":["any","any"]},{"topic":"item_topic","partition":0,"replicas":[1001,1002],"log_dirs":["any","any"]},{"topic":"event_topic","partition":4,"replicas":[1001,1002],"log_dirs":["any","any"]},{"topic":"event_topic","partition":9,"replicas":[1002,1001],"log_dirs":["any","any"]},{"topic":"event_topic","partition":6,"replicas":[1001,1002],"log_dirs":["any","any"]},{"topic":"event_topic","partition":3,"replicas":[1002,1001],"log_dirs":["any","any"]},{"topic":"event_topic","partition":8,"replicas":[1001,1002],"log_dirs":["any","any"]},{"topic":"profile_topic","partition":0,"replicas":[1001,1002],"log_dirs":["any","any"]},{"topic":"event_topic","partition":0,"replicas":[1001,1002],"log_dirs":["any","any"]},{"topic":"event_topic","partition":5,"replicas":[1002,1001],"log_dirs":["any","any"]},{"topic":"profile_topic","partition":2,"replicas":[1001,1002],"log_dirs":["any","any"]},{"topic":"event_topic","partition":2,"replicas":[1001,1002],"log_dirs":["any","any"]}]}
将上面得到期望的重新分配方式文件保存在一个 json 文件里面:reassignment-json-file.json,然后通过参数 —execute 执行分配:
该命令也可以用于以下使用场景:
查看 group 的消费情况
# group: 指定group id名字
./kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --describe --group test-group
# 示例:
# TOPIC: group对应的topic
# PARTITION:aprtition编号,从0开始0-5表示有6个partition
# CURRENT-OFFSET:此消费着当前已消费的offset
# LOG-END-OFFSET:生产者在此partition分区上已提交确认的offset
# LAG:两个offset的差值,就是常说的积压。此数值过大为异常。
# HOST:消费者所在的服务器ip
# CLIENT-ID:消费者的信息
./kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group test-group
2.删除group
删除 group
./kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --delete --group test-group
重新设置消费者位移
Earliest策略:把位移调整到当前最早位移处
bin/kafka-consumer-groups.sh --bootstrap-server kafka-host:port --group test-group --reset-offsets --all-topics --to-earliest –execute
Latest策略:把位移调整到当前最新位移处
bin/kafka-consumer-groups.sh --bootstrap-server kafka-host:port --group test-group --reset-offsets --all-topics --to-latest --execute
Current策略:把位移调整到当前最新提交位移处
bin/kafka-consumer-groups.sh --bootstrap-server kafka-host:port --group test-group --reset-offsets --all-topics --to-current --execute
Specified-Offset策略:把位移调整到指定位移处
bin/kafka-consumer-groups.sh --bootstrap-server kafka-host:port --group test-group --reset-offsets --all-topics --to-offset <offset> --execute
Shift-By-N策略:把位移调整到当前位移+N处(N可以是负值)
bin/kafka-consumer-groups.sh --bootstrap-server kafka-host:port --group test-group --topic test --reset-offsets --shift-by <offset_N> --execute
DateTime策略:(把位移调整到大于给定时间的最小位移处)
时间需要减8
bin/kafka-consumer-groups.sh --bootstrap-server kafka-host:port --group test-group --topic test --reset-offsets --to-datetime 2019-06-20T20:00:00.000 --execute
Duration策略:把位移调整到距离当前时间指定间隔的位移处,然后将位移调整到距离当前给定时间间隔的位移处,具体格式是 PnDTnHnMnS。
以字母 P 开头,后面由 4 部分组成,即 D、H、M 和 S,分别表示天、小时、分钟和秒。
bin/kafka-consumer-groups.sh --bootstrap-server kafka-host:port --group test-group --reset-offsets --by-duration PT0H30M0S --execute
# 设置 topic 过期时间(单位 毫秒)
### 3600000 毫秒 = 1小时
./bin/kafka-configs.sh --zookeeper 127.0.0.1:2181 --alter --entity-name topic-devops-elk-log-hechuan-huanbao --entity-type topics --add-config retention.ms=3600000
# 查看 topic 配置
./bin/kafka-configs.sh --zookeeper 127.0.0.1:2181 --describe --entity-name topic-devops-elk-log-hechuan-huanbao --entity-type topics
# 连接到test-topic,然后通过输入+会车生产消息
$ bin/kafka-console-producer.sh --broker-list kafka-host:port --topic test-topic --producer-property
>
# --from-beginning: 指定从开始消费消息,否则会从最新的地方开始消费消息
$ bin/kafka-console-consumer.sh --bootstrap-server kafka-host:port --topic test-topic --group test-group --from-beginning --consumer-property
# 测试生产者
# 向指定主题发送了 1 千万条消息,每条消息大小是 1KB
# 它会打印出测试生产者的吞吐量 (MB/s)、消息发送延时以及各种分位数下的延时
$ bin/kafka-producer-perf-test.sh --topic test-topic --num-records 10000000 --throughput -1 --record-size 1024 --producer-props bootstrap.servers=kafka-host:port acks=-1 linger.ms=2000 compression.type=lz4
2175479 records sent, 435095.8 records/sec (424.90 MB/sec), 131.1 ms avg latency, 681.0 ms max latency.
4190124 records sent, 838024.8 records/sec (818.38 MB/sec), 4.4 ms avg latency, 73.0 ms max latency.
10000000 records sent, 737463.126844 records/sec (720.18 MB/sec), 31.81 ms avg latency, 681.00 ms max latency, 4 ms 50th, 126 ms 95th, 604 ms 99th, 672 ms 99.9th.
# 测试消费者性能
$ bin/kafka-consumer-perf-test.sh --broker-list kafka-host:port --messages 10000000 --topic test-topic
start.time, end.time, data.consumed.in.MB, MB.sec, data.consumed.in.nMsg, nMsg.sec, rebalance.time.ms, fetch.time.ms, fetch.MB.sec, fetch.nMsg.sec
2019-06-26 15:24:18:138, 2019-06-26 15:24:23:805, 9765.6202, 1723.2434, 10000000, 1764602.0822, 16, 5651, 1728.1225, 1769598.3012
kafka 读写的单位是 partition,因此将一个 topic 拆分为多个 partition 可以提高吞吐量。但是这里有个前提,就是不同 partition 需要位于不同的磁盘(可以在同一个机器)。如果多个 partition 位于同一个磁盘,那么意味着有多个进程同时对一个磁盘的多个文件进行读写,使得操作系统会对磁盘读写进行频繁调度,也就是破坏了磁盘读写的连续性。
说明:如果你想了解更多关于:大数据运维相关的系统环境准备、基础环境安装、集群部署以及应用组件安装等全方位的技术的问题。例如:从环境搭建/集群部署,内存扩容/问题排查,数据迁移等助你轻松应对数据管理的复杂性。可以联系我:15928721005
推荐使用最新的 G1 来代替 CMS 作为垃圾回收器。推荐 Java 使用的最低版本为 JDK 1.7u51。
G1 相比较于 CMS 的优势:
为了大幅度提高 producer 写入吞吐量,需要定期批量写文件。
有 2 个参数可配置:
log.flush.interval.messages = 100000
:
每当 producer 写入 100000 条数据时,就把数据刷到磁盘log.flush.interval.ms=1000
:
每隔 1 秒,就刷一次盘当 kafka server 的被写入海量消息后,会生成很多数据文件,且占用大量磁盘空间,如果不及时清理,可能导致磁盘空间不够用,kafka 默认是保留 7 天。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。