Apache Kafka是基于发布订阅的容错消息系统。
消息系统负责将数据从一个应用程序传输到另一个应用程序,因此应用程序可以专注于数据,但不担心如何共享它。 分布式消息传递基于可靠消息队列的概念。 消息在客户端应用程序和消息传递系统之间异步排队。 有两种类型的消息模式可用: 一种是点对点,另一种是发布订阅(pub-sub)消息系统。
在点对点系统中,消息被保留在队列中。 一个或多个消费者可以消耗队列中的消息,但是特定消息只能由最多一个消费者消费。 一旦消费者读取队列中的消息,它就从该队列中消失。 该系统的典型示例是订单处理系统,其中每个订单将由一个订单处理器处理,但多个订单处理器也可以同时工作。
在发布 - 订阅系统中,消息被保留在主题中。 与点对点系统不同,消费者可以订阅一个或多个主题并使用该主题中的所有消息。 在发布 - 订阅系统中,消息生产者称为发布者,消息使用者称为订阅者。 一个现实生活的例子是Dish电视,它发布不同的渠道,如运动,电影,音乐等,任何人都可以订阅自己的频道集,并获得他们订阅的频道时可用。
可靠性 - Kafka是分布式,分区,复制和容错的。数据流分区(Partition)存储在多个机器上。
可扩展性 - Kafka消息传递系统轻松缩放,无需停机。
耐用性 - Kafka使用分布式提交日志,这意味着消息会尽可能快地保留在磁盘上,因此它是持久的。
性能 - Kafka对于发布和订阅消息都具有高吞吐量。 即使存储了许多TB的消息,它也保持稳定的性能。
指标 - Kafka通常用于操作监控数据。 这涉及聚合来自分布式应用程序的统计信息,以产生操作数据的集中馈送。
日志聚合解决方案 - Kafka可用于跨组织从多个服务收集日志,并使它们以标准格式提供给多个服务器。
流处理 - 流行的框架(如Storm和Spark Streaming)从主题中读取数据,对其进行处理,并将处理后的数据写入新主题,供用户和应用程序使用。 Kafka的强耐久性在流处理的上下文中也非常有用。
看这么个场景。A 系统发送数据到 BCD 三个系统,通过接口调用发送。如果 E 系统也要这个数据呢?那如果 C 系统现在不需要了呢?A 系统负责人几乎崩溃…
在这个场景中,A 系统跟其它各种乱七八糟的系统严重耦合,A 系统产生一条比较关键的数据,很多系统都需要 A 系统将这个数据发送过来。A 系统要时时刻刻考虑 BCDE 四个系统如果挂了该咋办?要不要重发,要不要把消息存起来?头发都白了啊!
如果使用 MQ,A 系统产生一条数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消费。如果新系统需要数据,直接从 MQ 里消费即可;如果某个系统不需要这条数据了,就取消对 MQ 消息的消费即可。这样下来,A 系统压根儿不需要去考虑要给谁发送数据,不需要维护这个代码,也不需要考虑人家是否调用成功、失败超时等情况。
总结:通过一个 MQ,Pub/Sub 发布订阅消息这么一个模型,A 系统就跟其它系统彻底解耦了。
再来看一个场景,A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s,用户感觉搞个什么东西,慢死了慢死了。用户通过浏览器发起请求,等待个 1s,这几乎是不可接受的。
一般互联网类的企业,对于用户直接的操作,一般要求是每个请求都必须在 200 ms 以内完成,对用户几乎是无感知的。
如果使用 MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应给用户,总时长是 3 + 5 = 8ms,对于用户而言,其实感觉上就是点个按钮,8ms 以后就直接返回了,爽!网站做得真好,真快!
每天 0:00 到 12:00,A 系统风平浪静,每秒并发请求数量就 50 个。结果每次一到 12:00 ~ 13:00 ,每秒并发请求数量突然会暴增到 5k+ 条。但是系统是直接基于 MySQL 的,大量的请求涌入 MySQL,每秒钟对 MySQL 执行约 5k 条 SQL。
一般的 MySQL,扛到每秒 2k 个请求就差不多了,如果每秒请求到 5k 的话,可能就直接把 MySQL 给打死了,导致系统崩溃,用户也就没法再使用系统了。
但是高峰期一过,到了下午的时候,就成了低峰期,可能也就 1w 的用户同时在网站上操作,每秒中的请求数量可能也就 50 个请求,对整个系统几乎没有任何的压力。
如果使用 MQ,每秒 5k 个请求写入 MQ,A 系统每秒钟最多处理 2k 个请求,因为 MySQL 每秒钟最多处理 2k 个。A 系统从 MQ 中慢慢拉取请求,每秒钟就拉取 2k 个请求,不要超过自己每秒能处理的最大请求数量就 ok,这样下来,哪怕是高峰期的时候,A 系统也绝对不会挂掉。而 MQ 每秒钟 5k 个请求进来,就 2k 个请求出去,结果就导致在中午高峰期(1 个小时),可能有几十万甚至几百万的请求积压在 MQ 中。
这个短暂的高峰期积压是 ok 的,因为高峰期过了之后,每秒钟就 50 个请求进 MQ,但是 A 系统依然会按照每秒 2k 个请求的速度在处理。所以说,只要高峰期一过,A 系统就会快速将积压的消息给解决掉。
MQ 一挂,整套系统崩溃
怎么保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证消息传递的顺序性?
A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。
消息的发送者叫 Producer,消息的使用者和接受者是 Consumer。生产者采用推(push)模式将消息发布到broker,每条消息都被追加(append)到分区(patition)中,属于顺序写磁盘(顺序写磁盘效率比随机写内存要高,保障kafka吞吐率)。消费者采用拉取(pull)方式获取消息并进一步处理,消费者自己记录消费状态,每个消费者互相独立地顺序读取每个分区的消息。
Kafka 集群中有很多台 Server,其中每一台 Server 都可以存储消息,将每一台 Server 称为一个 kafka 实例,也叫做 broker。
一个 topic 里保存的是同一类消息,相当于对消息的分类,每个 producer 将消息发送到 kafka 中,都需要指明要存的 topic 是哪个,也就是指明这个消息属于哪一类。
每个 topic 都可以分成多个 partition,每个 partition 在存储层面是 append log 文件。任何发布到此 partition 的消息都会被直接追加到 log 文件的尾部。为什么要进行分区呢?最根本的原因就是:kafka基于文件进行存储,当文件内容大到一定程度时,很容易达到单个磁盘的上限,因此,采用分区的办法,一个分区对应一个文件,这样就可以将数据分别存储到不同的server上去,另外这样做也可以负载均衡,容纳更多的消费者。
一个分区对应一个磁盘上的文件,而消息在文件中的位置就称为 offset(偏移量),offset 为一个 long 型数字,它可以唯一标记一条消息。由于kafka 并没有提供其他额外的索引机制来存储 offset,文件只能顺序的读写,所以在kafka中几乎不允许对消息进行“随机读写”。
kafka 还可以配置 partitions 需要备份的个数(replicas),每个 partition 将会被备份到多台机器上,以提高可用性,备份的数量可以通过配置文件指定。同一个partition可能会有多个replication(对应 server.properties 配置中的 default.replication.factor=N)。没有replication的情况下,一旦broker 宕机,其上所有 patition 的数据都不可被消费,同时producer也不能再将数据存于其上的patition。
这种冗余备份的方式在分布式系统中是很常见的,那么既然有副本,就涉及到对同一个文件的多个备份如何进行管理和调度。kafka 采取的方案是:每个 partition 选举一个 server 作为“leader”,由 leader 负责所有对该分区的读写,其他 server 作为 follower 只需要简单的与 leader 同步,保持跟进即可。如果原来的 leader 失效,会重新选举由其他的 follower 来成为新的 leader。
至于如何选取 leader,实际上如果我们了解 ZooKeeper,就会发现其实这正是 Zookeeper 所擅长的,Kafka 使用 ZK 在 Broker 中选出一个 Controller,用于 Partition 分配和 Leader 选举。
另外,这里我们可以看到,实际上作为 leader 的 server 承担了该分区所有的读写请求,因此其压力是比较大的,从整体考虑,从多少个 partition 就意味着会有多少个leader,kafka 会将 leader 分散到不同的 broker 上,确保整体的负载均衡。
即与Leader数据不一致的副本列表。
In-sync Replicas(副本同步列表)。ISR中的副本都是与Leader数据一致的副本,不在ISR中的Follower副本是与Leader数据不一致的。Leader副本天然就在 ISR 中,但ISR不只是Follower副本集合,是一个动态调整的集合,由Leader负责维护。如果一个follower的同步时间过长(大于阈值),就会被ISR剔除。
即已分配的副本列表,是指某个Partition的所有副本。AR = ISR + OSR
俗称高水位,HighWatermark的缩写。具体含义看下图:
Broker就是kafka实例,即Kafka集群通常由多个Broker组成以保持负载平衡。 Broker是无状态的,所以他们使用ZooKeeper来维护它们的集群状态。 一个Broker可以每秒处理数十万次读取和写入,每个Broker可以处理TB的消息,而没有性能影响。 Kafka经纪人领导选举可以由ZooKeeper完成。
ZooKeeper用于管理和协调Broker。 ZooKeeper服务主要用于通知生产者和消费者Kafka系统中存在任何新Broker或Kafka系统中Broker失败。 根据Zookeeper接收到关于Broker的存在或失败的通知,然后生产者和消费者采取决定并开始与某些其他Broker协调他们的任务。Kafka实例通过 Zookeeper 集群共享信息。Kafka实例 在 Zookeeper 中存储基本元数据,例如关于主题,代理,消费者偏移(队列读取器)等的信息。
Producers(生产者)
生产者将数据推送给Broker。 当新Broker启动时,所有生产者搜索它并自动向该新Broker发送消息。 Kafka生产者不等待来自Broker的确认,并且发送消息的速度与Broker可以处理的一样快。producer不需要在zookeeper中注册。
因为Broker是无状态的,这意味着消费者必须通过使用分区偏移来维护已经消耗了多少消息。 如果消费者确认特定的消息偏移,则意味着消费者已经消费了所有先前的消息。 消费者向Broker发出异步拉取请求,以具有准备好消耗的字节缓冲区。 消费者可以简单地通过提供偏移值来快退或跳到分区中的任何点。 消费者偏移值由ZooKeeper通知。消费者需要在zookeeper中注册。
每个Consumer属于一个特定的Consumer Group,一条消息可以发送到多个不同的Consumer Group,但是一个Consumer Group中只能有一个Consumer能够消费该消息
- 生产者定期向主题发送消息。
- Broker存储该特定主题配置的分区中的所有消息。 它确保消息在分区之间平等共享。 如果生产者发送两个消息并且有两个分区,Broker 将在第一分区中存储一个消息,在第二分区中存储第二消息。
- 消费者订阅特定主题。
- 一旦消费者订阅主题,Kafka 将向消费者提供主题的当前偏移,并且还将偏移保存在 Zookeeper 系统中。
- 消费者将定期请求 Kafka (如100 Ms)新消息。
- 一旦 Kafka 收到来自生产者的消息,它将这些消息转发给消费者。
- 消费者将收到消息并进行处理。
- 一旦消息被处理,消费者将向 Kafka 代理发送确认。
- 一旦 Kafka 收到确认,它将偏移更改为新值,并在 Zookeeper 中更新它。
- 以上流程将重复,直到消费者停止请求。
- 消费者可以随时回退/跳到所需的主题偏移量,并阅读所有后续消息。
订阅具有相同 Group ID 的主题的消费者被认为是单个组,并且消息在它们之间共享。工作流程如下:
- 生产者以固定间隔向某个主题发送消息。
- Broker存储该特定主题配置的分区中的所有消息。
- 单个消费者订阅特定主题,假设 Topic-01 为 Group ID 为 Group-1 。
- Kafka 与消费者交互,直到新消费者以相同的组 ID 订阅相同主题Topic-01 。
- 一旦新消费者到达,Kafka 将其操作切换到共享模式,并在两个消费者之间共享数据。 此共享将继续,直到用户数达到为该特定主题配置的分区数。
- 一旦消费者的数量超过分区的数量,新消费者将不会接收任何进一步的消息,直到现有消费者取消订阅任何一个消费者。 出现这种情况是因为 Kafka 中的每个消费者将被分配至少一个分区,并且一旦所有分区被分配给现有消费者,新消费者将必须等待。
将消息发送给Broker并形成可供消费者消费的消息数据的过程如下:
- Producer先从Zookeeper中找到Partition的Leader
- Producer将消息发送给分区的Leader。
- Leader将消息接入本地的Log,并通知ISR的Followers。
- ISR中的Followers从Leader中pull消息,写入本地Log后向Leader发送ACK。
- Leader收到所有ISR中的Followers的ACK后,增加HW并向Producer发送ACK,表示消息写入成功。
- 连接 ZK 集群,拿到对应 topic 的 partition 信息和 partition 的 leader 的相关信息
- 连接到对应 leader 对应的 broker
- consumer 将自己保存的 offset 发送给 leader
- leader 根据 offset 等信息定位到 segment(索引文件和日志文件)
- 根据索引文件中的内容,定位到日志文件中该偏移量对应的开始位置读取相应长度的数据并返回给 consumer
在通过API方式发布消息时,生产者是以Record为消息进行发布的。Record中包含key与value,value才是消息本身,而key用于路由消息所要存放Partition。消息要写入到哪个Partition并不是随机的,而是由路由策略决定。
- 如果指定了Partition,则直接写入到指定的Partition。
- 如果没有指定Partition但指定了key,则通过对key的hash值与Partition数量取模,结果就是要选出的Partition索引。
- 如果Partition和key都未指定,则使用轮询算法选出一个Partition。
- 增加分区时,Partition内的消息不会重新进行分配,随着数据继续写入,新分区才会参与再平衡
Rebalance本质上是一种协议,规定了一个Consumer Group下的所有Consumer如何达成一致,来分配订阅Topic的每个分区。如某个Group下有20个Consumer实例,订阅了一个具有100个分区的Topic。正常情况下,Kafka平均会为每个Consumer分配5个分区,分区的分配的过程就叫Rebalance。Consumer Group触发Rebalance的条件有 3 个:
- 组成员数发生变更。如有新的Consumer实例加入组或者离开组,或有Consumer实例崩溃从组中删除。
- 订阅Topic数发生变更。Consumer Group可以使用正则表达式的方式订阅主题,在Consumer Group运行过程中,如果新创建一个满足正则匹配条件的Topic,那么Consumer Group就会触发Rebalance。
- 订阅Topic的分区数发生变更。Kafka当前只能允许增加一个Topic的分区数。当分区数增加时,就会触发订阅Topic的所有Consumer Group开启Rebalance。
Rebalance发生时,Consumer Group下所有的Consumer实例都会协调在一起共同参与。Kafka默认提供了3种Topic分区的分配策略,每个Consumer实例都能够得到较为平均的分区数。
Rebalance的缺点如下:
- Rebalance过程对Consumer Group消费过程有极大的影响。在Rebalance过程中,所有Consumer实例都会停止消费,等待Rebalance完成。
- Rebalance过程中所有Consumer实例共同参与,全部重新分配所有分区,更高效的做法是尽量减少分配方案的变动。
- Rebalance过程太慢。
Coordinator一般指的是运行在每个Broker上的Group Coordinator进程,用于管理Consumer Group中的各个成员,主要用于offset位移管理和Rebalance。一个Coordinator可以同时管理多个消费者组。
kafka引入Coordinator有其历史背景,原来consumer信息依赖于Zookeeper存储,当代理或消费者发生变化时,引发消费者平衡,此时消费者之间是互不透明的,每个消费者和Zookeeper单独通信,容易造成羊群效应和脑裂问题。
为了解决这些问题,kafka引入了Coordinator。服务端引入组协调器(Group Coordinator),消费者端引入消费者协调器(Consumer Coordinator)。每个Broker启动的时候,都会创建Group Coordinator实例,管理部分消费组(集群负载均衡)和组下每个消费者消费的偏移量(offset)。每个Consumer实例化时,同时实例化一个Consumer Coordinator对象,负责同一个消费组下各个消费者和服务端组协调器之前的通信。
1(默认): 这意味着producer在ISR中的leader已成功收到数据并得到确认。如果leader宕机了,则会丢失数据。
0: 这意味着producer无需等待来自broker的确认而继续发送下一批消息。这种情况下数据传输效率最高,但是数据可靠性确是最低的。
-1: producer需要等待ISR中的所有follower都确认接收到数据后才算一次发送完成,可靠性最高。但是这样也不能保证数据不丢失,比如当ISR中只有leader时(前面ISR那一节讲到,ISR中的成员由于某些情况会增加也会减少,最少就只剩一个leader),这样就变成了acks=1的情况。
如果要提高数据的可靠性,在设置request.required.acks=-1的同时,也要min.insync.replicas这个参数(可以在broker或者topic层面进行设置)的配合,这样才能发挥最大的功效。min.insync.replicas这个参数设定ISR中的最小副本数是多少,默认值为1,当且仅当request.required.acks参数设置为-1时,此参数才生效。如果ISR中的副本数少于min.insync.replicas配置的数量时,客户端会返回异常:org.apache.kafka.common.errors.NotEnoughReplicasExceptoin: Messages are rejected since there are fewer in-sync replicas than required。
topic的配置:replication.factor>=3,即副本数至少是3个;2<=min.insync.replicas<=replication.factor
broker的配置:leader的选举条件unclean.leader.election.enable=false
producer的配置:request.required.acks=-1(all),producer.type=sync
zk 3.6.3 172.16.212.21/172.16.212.22/172.16.212.23
java 1.8 172.16.212.21/172.16.212.22/172.16.212.23
kafka 2.8.0 172.16.212.21/172.16.212.22/172.16.212.23
详见 https://blog.csdn.net/qq_35550345/article/details/116208174
wget https://mirror-hk.koddos.net/apache/kafka/2.8.0/kafka_2.13-2.8.0.tgz
mkdir -p /opt/work
mkdir -p /opt/data/kafka
tar xvfz kafka_2.13-2.8.0.tgz -C /opt/work
ln -s /opt/work/kafka_2.13-2.8.0 /opt/work/kafka
# 编辑配置文件 server.properties
vim /opt/work/kafka_2.13-2.8.0/conf/server.properties
##Broker的ID,每个broker必须又有唯一的值
broker.id=1
##节点ip和端口
listeners=PLAINTEXT://172.16.212.21:9092
advertised.listeners=PLAINTEXT://172.16.212.21:9092
num.network.threads=3
num.io.threads=8
num.partitions=1
num.recovery.threads.per.data.dir=3
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
log.dirs=/opt/data/kafka
log.retention.hours=168
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
zookeeper.connect=172.16.212.21:2181,172.16.212.22:2181,172.16.212.23:2181
zookeeper.connection.timeout.ms=6000
min.insync.replicas = 2
offsets.topic.replication.factor=3
transaction.state.log.replication.factor=3
transaction.state.log.min.isr=3
auto.create.topics.enable=false
# 启动
# /opt/work/kafka_2.13-2.8.0/bin/kafka-server-start.sh --daemon ../config/server.properties
# systemd管理kafka
vim /etc/systemd/system/kafka.service
[Unit]
Description=Apache Kafka server (broker)
After=network.target zookeeper.service
[Service]
Type=simple
User=root
Group=root
Environment=LOG_DIR=/opt/logs/kafka
ExecStart=/opt/work/kafka_2.13-2.8.0/bin/kafka-server-start.sh /opt/work/kafka/config/server.properties
ExecStop=/opt/work/kafka_2.13-2.8.0/bin/kafka-server-stop.sh
Restart=always
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl start kafka
# 报错了 /opt/work/kafka_2.13-2.8.0/bin/kafka-run-class.sh: line 330: exec: java: not found
# 修复方法 ln -s /usr/local/jdk1.8.0_261/bin/java /usr/bin/java
systemctl enable kafka
systemctl status kafka
# 启动producer
./kafka-console-producer.sh --broker-list 172.16.212.21:9092 --topic test
# 随便输入信息
# 查看消息是否到达了broker
./kafka-console-consumer.sh --bootstrap-server 172.16.212.21:9092 --topic test --from-beginning
# 这边都能看到随便输入的信息
# 查看comsumer有没有在正常消费到数据
# 消费test 最开始至现在所有的数据
./kafka-console-consumer.sh --bootstrap-server 172.16.212.21:9092 --topic test --from-beginning
# 只消费当前之后所有数据
./kafka-console-consumer.sh --bootstrap-server 172.16.212.21:9092 --topic test
broker.id=1
Broker的ID,每个broker必须又有唯一的值。
listeners=PLAINTEXT://172.16.3.177:9092
Socket服务器监听的地址,如果没有设置,则监听java.net.InetAddress.getCanonicalHostName()返回的地址
advertised.listeners=PLAINTEXT://your.host.name:9092
broker通知到producers和consumers的主机地址和端口号。如果未设置,使用listeners的配置。否则,使用java.net.InetAddress#.getCanonicalHostName()返回的值。如果均无设置,拿到的值为localhot:9092,将造成无法连接其他机器
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL
listener名称到安全协议。默认所有的listener使用相同的安全协议。PLAINTEXT为明码文本协议
num.network.threads=3
服务器用来从网络接收请求和发送响应数据到网络的线程数
num.io.threads=8
服务器用来处理请求的线程数,可能包含磁盘I/O的线程。
socket.send.buffer.bytes=102400
服务器发送数据的缓存大小。
socket.receive.buffer.bytes=102400
服务器接收数据的缓存大小。
socket.request.max.bytes=104857600
socket服务器接收的单个request大小的最大值。
log.dirs=/home/logs/kafka
Kafka存储log文件的目录,多个目录用逗号分隔。
num.partitions=10
topic的默认分割的分区个数。多分区允许消费者并行获取数据,但这也会造成brokers交叉保存多个文件。
num.recovery.threads.per.data.dir=2
当Kafka启动时恢复数据和关闭时保存数据到磁盘时使用的线程个数。
log.flush.interval.messages=10000
在持久化到磁盘前message最大接收条数。
log.flush.interval.ms=1000
持久化的最大时间间隔。
log.retention.hours=168
将已保存超过7天的数据删除。
log.retention.bytes=1073741824
基于数据大小的log保存策略。当分片的大小超过该值时,就会被删除。改功能不依赖于log.retention.hours。
log.segment.bytes=1073741824
单个分片的上限,达到该大小后会生成新的日志分片。
log.retention.check.interval.ms=300000
日志分片的检测时间间隔,每隔该事件会根据log保留策略决定是否删除log分片。
zookeeper.connect=172.16.3.177:12181,172.16.3.178:12181,172.16.3.179:12181
Zookeeper连接字符串。是一个使用逗号分隔的host:port字符串。
zookeeper.connection.timeout.ms=6000
连接zookeeper的超时时间。
group.initial.rebalance.delay.ms=0
在开发测试环境下该值设置为0,保证启动后马上可以使用。但在生产环境下,默认值3秒更适合。
unclean.leader.election.enable = false
默认值是false, 是否允许ISR集合外的副本参与leader选举, 如果参数设置为true,就有可能发生数据丢失和数据不一致的情况,Kafka的可靠性就会降低;而如果参数设置为false,Kafka的可用性就会降低
min.insync.replicas = 2
当producer设置request.required.acks为-1时,min.insync.replicas指定replicas的最小数目(必须确认每一个repica的写数据都是成功的),如果这个数目没有达到,producer会产生异常。
cleanup.policy
Default(默认值):deleteserver.properties:log.cleanup.policy
说明(解释):日志清理策略选择有:delete和compact主要针对过期数据的处理,或是日志文件达到限制的额度,会被 topic创建时的指定参数覆盖
delete.retention.ms
Default(默认值):86400000 (24 hours)server.properties:log.cleaner.delete.retention.ms
说明(解释): 对于压缩的日志保留的最长时间,也是客户端消费消息的最长时间,同log.retention.minutes的区别在于一个控制未压缩数据,一个控制压缩后的数据。会被topic创建时的指定参数覆盖
flush.messages
Default(默认值):Noneserver.properties:log.flush.interval.messages
说明(解释): log文件”sync”到磁盘之前累积的消息条数,因为磁盘IO操作是一个慢操作,但又是一个”数据可靠性"的必要手段,所以此参数的设置,需要在"数据可靠性"与"性能"之间做必要的权衡.如果此值过大,将会导致每次"fsync"的时间较长(IO阻塞),如果此值过小,将会导致"fsync"的次数较多,这也意味着整体的client请求有一定的延迟.物理server故障,将会导致没有fsync的消息丢失.
flush.ms
Default(默认值):Noneserver.properties:log.flush.interval.ms
说明(解释):仅仅通过interval来控制消息的磁盘写入时机,是不足的.此参数用于控制"fsync"的时间间隔,如果消息量始终没有达到阀值,但是离上一次磁盘同步的时间间隔达到阀值,也将触发.
index.interval.bytes
Default(默认值):4096server.properties:log.index.interval.bytes
说明(解释):当执行一个fetch操作后,需要一定的空间来扫描最近的offset大小,设置越大,代表扫描速度越快,但是也更耗内存,一般情况下不需要搭理这个参数
message.max.bytes
Default(默认值):1,000,000server.properties: 表示消息的最大大小,单位是字节 说明(解释):当执行一个fetch操作后,需要一定的空间来扫描最近的offset大小,设置越大,代表扫描速度越快,但是也更好内存,一般情况下不需要搭理这个参数
min.cleanable.dirty.ratio
Default(默认值):0.5server.properties:log.cleaner.min.cleanable.ratio
说明(解释):日志清理的频率控制,越大意味着更高效的清理,同时会存在一些空间上的浪费,会被topic创建时的指定参数覆盖
retention.bytes
Default(默认值):Noneserver.properties:log.retention.bytes
说明(解释): topic每个分区的最大文件大小,一个topic的大小限制 = 分区数*log.retention.bytes。-1没有大小限log.retention.bytes和log.retention.minutes任意一个达到要求,都会执行删除,会被topic创建时的指定参数覆盖
retention.ms
Default(默认值):Noneserver.properties:log.retention.minutes
说明(解释): 数据存储的最大时间超过这个时间会根据log.cleanup.policy设置的策略处理数据,也就是消费端能够多久去消费数据 log.retention.bytes和log.retention.minutes达到要求,都会执行删除,会被topic创建时的指定参数覆盖
segment.bytes
Default(默认值):1 GBserver.properties:log.segment.bytes
说明(解释): topic的分区是以一堆segment文件存储的,这个控制每个segment的大小,会被topic创建时的指定参数覆盖
segment.index.bytes
Default(默认值):10 MBserver.properties:log.index.size.max.bytes
说明(解释):对于segment日志的索引文件大小限制,会被topic创建时的指定参数覆盖
log.roll.hours
Default(默认值):7 daysserver.properties:log.index.size.max.bytes
说明(解释): 这个参数会在日志segment没有达到log.segment.bytes设置的大小,也会强制新建一个segment会被 topic创建时的指定参数覆盖
cd /opt/work/kafka/bin
# 创建topic
./kafka-topics.sh --bootstrap-server 172.16.212.21:9092 --create --topic test --partitions 2 --replication-factor 3
# 查看topic信息
./kafka-topics.sh --bootstrap-server 172.16.212.21:9092 --describe --topic test
# 增加指定topic的分区数量
./kafka-topics.sh --bootstrap-server 172.16.212.21:9092 --alter --topic test --partitions 3
# 删除topic
./kafka-topics.sh --bootstrap-server 172.16.212.21:9092 --delete --topic test
# 查看消息堆积情况
./kafka-consumer-groups.sh --bootstrap-server 172.16.212.21:9092 --describe --group test
# 查看正在运行的消费组
./kafka-consumer-groups.sh --bootstrap-server 172.16.212.21:9092 --list
功能 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
---|---|---|---|---|
单机吞吐量 | 万级,比 RocketMQ 和 Kafka 低一个数量级 | 同 ActiveMQ | 10万级,支持高吞吐 | 10万级,高吞吐,一般配合大数据类的系统进行实时计算、日志采集等场景 |
时效性 | 毫秒级 | 微秒级,这是 RabbitMQ 的一大特性,低延迟 | 毫秒级 | 延迟在毫秒级以内 |
可用性 | 高,基于主从架构实现高可用 | 同 ActiveMQ | 非常高,分布式架构 | 非常高,分布式,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用 |
消息可靠性 | 有较低的概率丢失数据 | 基本不丢 | 经过参数优化配置,可以做到 0 丢失 | 同RocketMQ |
消息持久化 | 内存,数据库 | 内存,磁盘文件 | 磁盘文件 | 内存,磁盘文件 |
消息堆积能力 | 支持(有上限,当消息过期或存储设备溢出时,会终结它) | 支持(内存堆积达到特定阈值可能会影响性能) | 百亿级别会影响性能 | 支持,但达到阈值也会影响性能 |
消息回溯 | 支持 | 不支持 | 支持 | 不支持 |
消费模型 | Push / Pull | Push / Pull | Push / Pull | Pull |
定时消息 | 支持 | 支持 | 支持(只支持18个固定 Level) | 不支持 |