kafka与ZK的关系

利用ZK的 有序节点、临时节点和监听机制,ZK帮kafka做了:
配置中心(管理Broker、Topic、Partition、Consumer的信息,包括元数据的变动)
负载均衡、命名服务、分布式通知、集群管理和选举、分布式锁

kafka架构

1、Broker

kafka作为一个中间件,存储和转发消息,他做的事情有点像中介,kafka的服务叫做Broker,默认端口9092;生产者和消费者都需要和这个Broker建立一个连接,才可以实现消息的收发。

2、消息

客户端之间传输的数据叫做消息或者记录Record,Record是一个KV键值对
生产者对应的封装类是ProducerRecord
消费者对应的封装类是ConsumerRecord
消息传输过程中需要序列化,所以代码里要指定序列化工具
消息在服务端存储格式:RecordBatch/Record

3、生产者

为了提升消息发送速率,生产者不是逐条发送消息给Broker,而是批量发送的,
多少条发送一次由一个参数决定:

  1. props.put("batch.size",16384)

4、消费者

消费者获取消息有两种方式:pull模式/push模式
Pull模式:消息放在Broker,消费者自己决定什么时候去获取
Push模式:消息放在Consumer,只要有消息达到Broker就直接推送给消费者
RabbitMQ Consumer既支持push又支持pull,一般用的是push。
kafka只有pull模式,在push模式下,如果消息生产速率远远大于消费者消耗速率,消费者就会不堪重负,直到挂掉。

  1. 消费者可以自己控制一次到底获取多少条消息
  2. max.poll.records
  3. 默认 500 。在poll方法里可以指定

5、Topic

生产者和消费者如何关联起来的?答案是通过队列关联起来,即生产者发送消息到指定的队列,消费者从指定的队列获取消息。
在kafka里,这个队列叫做Topic,是一个逻辑概念,可以理解为一组消息的集合(不同业务用途的消息)。
生产者和Topic以及Topic和消费者的关系都是多对多,一般不建议这么做。
生产者发送消息时,如果topic不存在,会自动创建。有一个参数控制。
auto.create.topics.enable默认为true。如果要彻底删掉一个Topic,这个参数必须改成false,否则只要代码使用这个Topic,他就会自动创建。

6、Partition 与 Cluster

一个Topic中的消息太多,会带来两个问题:
1、不方便横向扩展,扩展机器而不是升级硬件
2、并发或者负载问题,所有客户端操作的都是同一个Topic,在高并发的场景下性能会大大下降
对一个Topic进行拆分(分片思想)。kafka引入了分区(Partition)的概念,一个Topic可以划分成多个分区,分区在创建Topic的时候指定,每个topic至少有一个分区。
创建Topic的命令:
./kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic topic-test
如果没有指定分区数,默认分区数是1个,可以修改参数num.partitions=1
replication-factor是topic的副本数
partition的思想类似于分表分库,实现的也是横向扩展负载的目的
每个partition都有一个物理目录,在配置的数据目录下(日志就是数据)/tmp/kafka-logs/
同Rabbit MQ不同的是,Partition里面的``消息被读取之后不会被删除``,所以同一批消息在一个Partition里面``顺序、追加的写入``。这也是kafka吞吐量大的一个很重要的原因
分区数量的选择,根据不同的机器网络环境不同,最好是通过性能测试脚本验证。

思考题

1、为什么kafka不用B+Tree?

kafka是写多、查少。如果kafka用B+Tree,首先会出现大量的B+Tree,大量插入数据带来的B+Tree的调整会非常耗性能。