一、认识Kafka
1. kafka适用场景
消息系统:kafka不仅具备传统的系统解耦、流量削峰、缓冲、异步通信、可扩展性、可恢复性等功能,还有其他消息系统难以实现的消息顺序消费及消息回溯功能。
存储系统:kafka把消息持久化到磁盘上,以及多副本机制,极大的降低的数据丢失风险,可以把kafka当做长期的数据存储系统使用。
流式处理平台:kafka为主流的流式处理框架提供了完整的处理类库
2. kafka架构
producer、consumer、broker、zookeeper
其中broker可看做kafka服务节点/实例,一个服务器可以部署一个或多个broker,多个broker组成Kafka集群。
zookeeper集群负责管理broker集群元数据、控制器的选举等。
3.主题与分区
消息按主题(Topic)进行分类,一个主题可以有多个分区(partition),一个分区就是一个可追加的Log文件,每个消息都分配一个特定的offset。
但offset不跨分区,所以只能保证单个分区内消息的有序性。
一个主题的分区,可以在不同的broker上,这样就能实现水平扩展。
每个分区又有多副本机制,一主多从,这样就具备了一定的容灾能力。但一般主从数据有一定滞后性,所以理论上是有一定数据丢失风险。
可以设置参数控制主从副本的数据滞后范围,replica.lag.time.max.ms。该参数并不能保证从副本一定会在指定时间内赶上主副本,若是从副本未在设定时间内赶上主副本,则会被认定为“不同步”,提出ISR集合,不能参与选举(也可以设置参数OSR的也可以参与选举)。
4. 分区副本同步机制ISR、OSR、HW、LEO
Kafka分区leader节点选举一般是在ISR(in-sync replicas)集合中选择节点,该集合是在主从数据同步滞后范围内的节点,也就是滞后没那么多的节点。OSR则是滞后太多或失效的节点。
Kafka一个分区的所有副本,同步最少数据的分区的offset,就是HW(heigh watermark)高水位线。就是水桶原理,最低位置处就是这个水桶的最高的水位线。HW之前的消息才能被消费者可见。在消息同步复制机制下,HW之前的消息,才会被认为是消息发送成功,也就是所有副本都持久化到了该消息。异步消息复制机制下,leader副本持久化了该消息即返回消息接收成功的ack。
但同步复制会极大影响性能,所以在异步复制下,kafka依靠ISR机制,容忍一定的复制滞后范围,权衡了性能和数据可靠性之间的关系。
二、生产者
1. 消息发送三种模式
即发即忘(fire-and forget)、同步(sync)、异步(async)
KafkaProducer的send方法返回Future对象,使用get()方法实现同步发送。
通过指定Callback实现异步发送。
public Future send(ProducerRecord rescord,CallBack callback)
2. 分区器
分区器是Kafka为消息分配分区的功能,若发送消息时ProducerRecord中没有指定partition,则使用默认分区器,若有消息有key,则对key做hash,在可用分区中选择,若没有key,则轮询所有分区。
分区器可以自定义,实现Partitioner,在生产者props中配置即可。
3. 生产者架构
生产者有两个线程,主线程负责创建消息及对消息做拦截、序列化、设置分区,打包到缓存批次里,被sender线程拉取走。
sender线程负责创建消息请求,发送消息、缓存已发送还未响应的消息及响应消息。
4. 生产者重要参数
acks:指定分区中必须有多少副本接收到,才算消息接收成功。1-leader副本接收成功即认为成功。0-不需要等待服务端响应。-1/all-全部副本接收成功才算成功。该参数为0性能最佳,可靠性最低,为-1可靠性最佳,性能最低。为1则是性能与可靠性的这种方案。
max.request.size:请求消息的最大值,默认1MB。
retries、retry.back.off.ms:重试次数与重试间隔时间
linger.ms:生产者发送ProducerBatch之前,等待更多消息加入的时间。默认为0 不等待,放大则会降低消息时效性,但提升吞吐量。
request.timeout.ms:生产者等待消息响应的超时时间。
三、消费者
1.消费者组合和消费者
kafka一个主题可以有多个消费者组,每个消费者组可以有多个消费者。
各个消费者组之间是独立的,同一个消息可以被多个消费者组消费。
一个消息在一个消费者组中,只能被一个消费者消费。
每个消费者组group.id唯一。
2.消费者和分区
一个主题可以有多个分区,每个分区都按一定策略均衡的分配给消费者进行订阅。
消费者数量若等于分区数量,1对1均衡分配。消费者数量小于分区数量,则消费者会分配多个分区。
但若消费者数量大于分区数量,则多出来的消费者不会被分配任何分区。所以消费者数量应小于等于分区数量。
3.投递模式
点对点(p2p):利用消费者组概念,所有消费者都在一个组内,实现一个消息只有一个消费者。
发布/订阅(pub/sub):利用消费者组概念,所有消费者在不同组中,实现广播效果。
4.消息消费及位移提交
使用poll(Duration)方法批量拉取到ConsumerRecords消息,此时主题中会记录最新消息被消费的位置lastConsumedOffset,以及下一个被拉取的位置position。当前拉取批次消息被消费完,则自动提交消费位移commited offset。
lastConsumedOffset到position之间的消息,就是正在被消费但还没提交位移的消息。消息消费完提交位移commitedOffset,则lastConsumedOffset变为最新位置
消费完成,位移提交
消费位移不仅可以自动提交,也可以手动提交。同步、异步,有参无参。commitSync、commitAsync方法。
5.消息重复及丢失
正是因为需要消费端提交位移,所以就可能出现某种原因导致未提交位移,消费者再次拉取,还是从上次拉取的位置开始,造成消息重复消费。所以用户需要做好幂等措施,kafka无法保证消息不重复。
又如果消费端拉取消息和处理消息是不同线程,或者异步提交位移。在已提交位移,但应用突然挂掉,导致消息丢失。所以需要在消息提交位移前用户自行缓存消息内容及消息处理状态,处理消息丢失后的重新消费逻辑。
6.消息回溯
若消息丢失,可以使用seek方法,指定分区及offset进行消息回溯,重新消费。
或者设置auto.offset.reset参数,从某个位置重新开始消费。
但有时候消息丢失了,也不一定依赖消息中间件处理。比如转账指令,指令消息发送方发送完转账消息,会对进行对账处理,也就是查询消息指令对应的业务指令状态,是否为已受理,过了一天转账指令仍然未被受理,则认为该消息未被消费、消费异常或者消息携带的业务数据有问题,则重新发起转账指令(消费端需做幂等校验)。
7.再均衡
再均衡是增减分区和消费者时,分区和消费者订阅关系再分配的行为。实现分区和消费者的可扩展性。
再均衡期间消费者是被暂停拉取到消息的,也不能提交位移。所以会导致消息重复消费问题。应当尽量避免。
或做好消息幂等。
再均衡有监听器:
1、再均衡开始前消费者停止拉取消息之后监听,可用于提交消费位移。
2、再均衡结束后,消费者拉取之前监听,可用于
8.拦截器
拦截消息消费之前(过滤过期消息)、位移提交之前(记录位移)
未完待续...
版权归原作者 独家记忆1995 所有, 如有侵权,请联系我们删除。