前言
kafka具有,高吞吐量、数据可持久化、易扩张、消费端维护等特点。kafka以topic进行数据分类,每个topic都会有分区,每个分区都会有副本。每条消息都有一个offset,通过维护offset可以实现对数据的指定消费。
Topic: 数据的分类
Partition: 每个topic会分为多个分区,每个分区都是一个有序队列,队列中的每条数据都有一个offset。每个分区都会有副本,并且每个分区都会选择一个Leader,负责读写,其它的为follower,负责数据的复制备份。
Message: 封装数据的基本单位
Producers: 数据的生产者。
Consumer: 数据的消费者,在kafka中消费者是以消费者组进行标识的,一个topic的分区由一个消费组的一个消费组消费,也就意味着,一个topic有n个分区,那么消费组中就有小于等于n个消费者。使用subscribe可以订阅主题,使用assign订阅主题的具体分区。
Broker: 缓存代理,kafka集群中的服务器被称为Broker
一、消息的发送流程
produc根据指定的partiton方法(hash、round-robin)将数据发送到指定的topic的分区中,数据到到broker中后,根据配置的保留时长进行保存。consumer从集群中pull数据,并控制获取的offset.
二、生产者分区策略
该策略是指,当生产者像kafka中发送一条数据,这条数据是放在topic中的那个分区上
direct:数据指明发送到某一个分区中
round-robin:循环方式,当record没有指定key也没有指定partition时,循环向partition写入消息,这是没有key值时候的默认策略
hash: 对key的hash值和partition取模来决定数据放在哪个分区上
自定义: 实现 Partitioner接口,实现该接口之后,通过配置来实现使用自定义的分区策略, properties.put("partitioner.class", "com.xx.kafka.XXX");
1. ProducerRecord
produce.sed(pr),生产者发送数据到kafka中时,数据是通过ProducerRecord进行封装。该类所需参数为
-- Topic (名字)
--partitionID //分区默认从0开始 int类型
--Key
-- Message
结论:当参数中,指明分区id则发送到指定的分区id中,如果没有指定分区id但传入key,则采用hash策略将数据发送到某个分区中;当参数既没有指明分区id和key,那么会采用round-robin策略均衡的发送到各分区中;如果既传入分区id也传入key,那么数据会发送到指定的分区中。当我们需要将数据发送到一个分区里面,我们可以指定分区id或者key.
2. Producer的内部实现
当数据发送到某一个分区的时候,并不直接发送到该分区中,而是存储在分区缓存中,当缓存满足一定的条件时候,才真正的发送到该分区中。我们可以通过配置文件配置缓存发送条件
bootstrap.servers=xxxx:9092,xxxx:9092,xxxx:9092
batch.size=1 //设置每个RecordBatch可以缓存的最大字节数
retries=0 //失败后的重试次数
acks=1 //数据阻塞设置,0:不管响应,一直发;1:成功响应后再发 ; 2:leader及foller都接收到数据再发。
reconnect.backoff.ms=10 //失败重新发送的时间间隔,不能太短。
retry.backoff.ms = 100 //设置每个RecordBatch的最长阻塞时间
max.in.flight.requests.per.connection = 5 //同一时间,每个Producer能够发送的消息上限
buffer.memory = 33554432 //设置所有RecordBatch的总共最大字节数
key.serializer=org.apache.kafka.common.serialization.StringSerializer //指定key的序列化
value.serializer=org.apache.kafka.common.serialization.StringSerializer //指定value的序列化
加载配置文件,也可以代码中直接配置
Properties properties = new Properties();
properties.load(new FileInputStream(configFile));
kafkaProducer = new KafkaProducer(properties);
三、消费者分区策略
Rang: 总的分区数/消费者线程总数=每个消费者线程应该消费的分区数。当还有余数的时候就将余数分别分发到另外的消费组线程中。 当分区数比较大的时候,会造成个别消费者线程压力大。但是消费者分区策略其实将主题的各个分区逐个分配到各个消费者中。消费者之间分配的分区最多差一个分区而已。
round-robin:将所有主题的分区组成TopicAndPartition列表,然后对TopAndPartition列表按照hashcode进行排序
partition.assignment.strategy参数选择range或roundrobin。 partition.assignment.strategy参数默认的值是range。