集群管理由zookeeper管理
1.每个broker启动后会在zookeeper上注册一个临时的broker registry,包含broker的ip地址和端口号,所存储的topics和partitions信息。
-
每个consumer启动后会在zookeeper上注册一个临时的consumer registry:包含consumer所属的consumer group以及订阅的topics。
-
每个consumer group关联一个临时的owner registry和一个持久的offset registry。对于被订阅的每个partition包含一个owner registry,内容为订阅这个partition的consumer id;同时包含一个offset registry,内容为上一次订阅的offset
kafka server能决定producer能不能产生新的topic 看给不给权限 可以在server定义partition数量
kafka 的topic过多 partition就会跟着增多,partition增加会增加磁盘读写的压力 性能会下降
主要是应为增加寻找partition的随机读取
性能
kafka的性能取决于你磁盘的以及服务器的速度
硬盘的顺序读写可达600MB/s
kafka application运行在内存中,producer发送的数据由内存接收缓存然后顺序写入磁盘
producer发送数据到kafka,由OS把内存中的缓存顺序写入到磁盘,同时记录offset
producer
func ProducerInit(addrs []string, maxSize int) (err error) {
config := sarama.NewConfig()
config.Producer.RequiredAcks = sarama.WaitForAll // 发送完数据需要leader和follow都确认
config.Producer.Partitioner = sarama.NewRandomPartitioner // 新选出一个partition
config.Producer.Return.Successes = true // 成功交付的消息将在success channel返回
// 连接kafka
producer, err = sarama.NewSyncProducer(addrs, config)
if err != nil {
fmt.Println("producer closed, err:", err)
return
}
logDataChan = make(chan *logData, maxSize)
go sendtoKafka()
return
}
producer的分为SyncProducer和AsyncProducer
即:sync 收到数据就往磁盘落盘
async即先缓存,通过设置缓存时间或者缓存大小,然后把数据一起落盘,减少磁盘读取次数,提升服务性能,但是增加数据丢失风险,和数据实时性。
type ProduceRequest struct {
TransactionalID *string
RequiredAcks RequiredAcks
Timeout int32
Version int16 // v1 requires Kafka 0.9, v2 requires Kafka 0.10, v3 requires Kafka 0.11
records map[string]map[int32]Records
}
producer连接时就需要告知应答方式
-
0 :不需要应答 最快 但不保证数据会不会丢
-
1:partition的leader应答即可
-
all,-1:即集群内所有broker都需应答 ,最慢 但保证数据不丢
producer 发送的三种模式
-
1:指定partition (可以做点对点传输) 负载均衡算法也可在这实现
-
2:根据key hash选择
-
3:轮询
consumer
kafka消费者给kafka返回的消息
type ConsumerMessage struct {
Headers []*RecordHeader // only set if kafka is version 0.11+
Timestamp time.Time // only set if kafka is version 0.10+, inner message timestamp
BlockTimestamp time.Time // only set if kafka is version 0.10+, outer (compressed) block timestamp
Key, Value []byte
Topic string
Partition int32
Offset int64 //告诉kafka我消费到哪了
}
kafka有个offset的概念,当每个消息被写进去后,都有一个offset,代表他的序号,然后consumer消费该数据之后,隔一段时间,会把自己消费过的消息的offset提交一下,代表我已经消费过了。下次我要是重启,就会继续从上次消费到的offset来继续消费 但是当我们直接kill进程了,再重启。这会导致consumer有些消息处理了,但是没来得及提交offset。等重启之后,少数消息就会再次消费一次。其他MQ也会有这种重复消费的问题,那么针对这种问题,我们需要从业务角度,考虑它的幂等性。
consumer连接成功后会在zookeeper上创建信息 读取的offset将保留到zookeeper上
broker
单体服务器实例