kafka是一个消息队列服务器,服务称为broker, 消息发送者称为producer, 消息接收者称为consumer;通常我们部署多个broker以提供高可用性的消息服务集群.
典型的是3个broker;消息以topic的形式发送到broker,消费者订阅topic,实现按需取用的消费模式;创建topic需要指定replication-factor(复制数目,通常=broker数目);
每个topic可能有多个分区(partition), 每个分区的消息内容不会重复:
Broker
Kafka集群包含一个或多个服务器,这种服务器被称为broker
Topic
每条发布到Kafka集群的消息都有一个类别,这个类别被称为topic。(物理上不同topic的消息分开存储,逻辑上一个topic的消息虽然保存于一个或多个broker上但用户只需指定消息的topic即可生产或消费数据而不必关心数据存于何处)
Partition
parition是物理上的概念,每个topic包含一个或多个partition,创建topic时可指定parition数量。每个partition对应于一个文件夹,该文件夹下存储该partition的数据和索引文件
Producer
负责发布消息到Kafka broker
Consumer
消费消息。每个consumer属于一个特定的consuer group(可为每个consumer指定group name,若不指定group name则属于默认的group)。使用consumer high level API时,同一topic的一条消息只能被同一个consumer group内的一个consumer消费,但多个consumer group可同时消费这一消息。
Producer在发布消息到某个Partition时,先通过Zookeeper找到该Partition的Leader,然后无论该Topic的Replication Factor为多少(也即该Partition有多少个Replica),Producer只将该消息发送到该Partition的Leader。Leader会将该消息写入其本地Log。每个Follower都从Leader pull数据。这种方式上,Follower存储的数据顺序与Leader保持一致。Follower在收到该消息并写入其Log后,向Leader发送ACK。一旦Leader收到了ISR中的所有Replica的ACK,该消息就被认为已经commit了,Leader将增加HW并且向Producer发送ACK。
为了提高性能,每个Follower在接收到数据后就立马向Leader发送ACK,而非等到数据写入Log中。因此,对于已经commit的消息,Kafka只能保证它被存于多个Replica的内存中,而不能保证它们被持久化到磁盘中,也就不能完全保证异常发生后该条消息一定能被Consumer消费。但考虑到这种场景非常少见,可以认为这种方式在性能和数据持久化上做了一个比较好的平衡。在将来的版本中,Kafka会考虑提供更高的持久性。
Consumer读消息也是从Leader读取,只有被commit过的消息(offset低于HW的消息)才会暴露给Consumer。
Leader会跟踪与其保持同步的Replica列表,该列表称为ISR(即in-sync Replica)
1. 安装前需要把zookeeper 安装好.参考另一个blog
2. 下载
http://kafka.apache.org/downloads
Binary downloads:
- Scala 2.11 - kafka_2.11-2.0.0.tgz (asc, sha512)
- Scala 2.12 - kafka_2.12-2.0.0.tgz (asc, sha512)
2.00 是版本,2.11,2.12 是编译scale 版本,我下载了 2.11的
3. 解压
tar zvfx kafka_2.12-2.0.0.tgz
4. 配置 config/server.properties 文件
#保证broker.id唯一性 本机为0 其它两台为1 2
broker.id=0
broker.id.generation.enable=falselisteners=PLAINTEXT://10.10.3.11:9092
#listeners=PLAINTEXT://10.10.3.12:9092
#listeners=PLAINTEXT://10.10.3.13:9092
port=9092#绑定本机IP地址 也可以不用设置
#host.name=172.16.18.233num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=1048576
socket.receive.buffer.bytes=1048576
socket.request.max.bytes=104857600log.dirs=/data/kafka
num.partitions=2
num.recovery.threads.per.data.dir=1log.flush.interval.messages=10000
log.flush.interval.ms=1000
log.retention.hours=960
log.retention.bytes=1073741824
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
log.cleanup.policy=delete
log.cleaner.enable=true#多台机器逗号分开
zookeeper.connect=10.10.3.11:2181,10.10.3.12:2181,10.10.3.13:2181
zookeeper.connection.timeout.ms=60000
zookeeper.session.timeout.ms=6000
zookeeper.sync.time.ms=3000#是否允许自动创建topic 允许为true,不允许为false,就需要通过命令创建topic
auto.create.topics.enable=false
delete.topic.enable=true
3台机器 配置一致就可以,除了broker.id,listen
单机版 也需要listen,注意一定是ip,不要写localhost
5. 后台启动
bin/kafka-server-start.sh -daemon config/server.properties
或者
nohup kafka-server-start.sh -daemon config/server.properties &
6.停止应执行脚本(传递ctrl+c的信号),这样加载避免检测错误,加载快
sh bin/kafka-server-stop.sh
7. 配置hosts
10.10.3.11 bj-6-dqy-msg-queue01
10.10.3.12 bj-6-dqy-msg-queue02
10.10.3.13 bj-6-dqy-msg-queue03
问题1 :
kafka Exception thrown when sending a message with key='null'
org.springframework.kafka.support.LoggingProducerListener [76] - Exception thrown when sending a message with key=’null’ and payload=’2017-11-14 15:36:53|iZbp1115ogry6vyp418vplZ|192.168.3.1|{“token”:”708037c594e04850bfd48f82fa862dd…’ to topic
解决:
/etc/hosts中加主机名和ip 映射