Kafka初步学习

kafka消息队列模式
点对点模式:一对一,消费者主动拉取数据,消息收到后消息清除
消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息
消息被消费以后,queue中不再有存储,所以消息消费者不可能消费到已经被消费的消息
queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。

发布订阅模式
消息生产者将消息发布到topic中,可以有多个topic
同时有多个消费者订阅消费该消息,消费数据后不删除
每个消费者相互独立,都可以消费到数据

专业名词:
事件:当你向kafka读取或写入数据时,你以事件的形式执行此操作,从概念上讲,事件具有键,值,时间戳和可选的元数据表头。
生产者
消费者:在kafka中,生产者和消费者完全解耦并且彼此不可知,生产者永远不需要等待消费者
主题:事件被组织并持久的存储在主题中,kafka中的主题始终是多生产者和多订阅者:一个主题可以是N个向其写入事件的生产者,以及订阅这些事件的
N个消费者。主题中的事件可以根据需要随时读取,与传统的消息传递系统不同,事件在消费后不会被删除。相反,您可以通过每个主题的配置设置来定义
kafka应该将您的事件保留多长时间,之后旧事件将被丢弃,kafka的性能在数据大小方面实际是恒定的,因此长时间存储数据是非常好的。

主题是分区的,这意味着一个主题分布在位于不同的kafka集群上的多个broker中,数据的这种分布式放置对于可伸缩性非常重要,因为它允许客户端应用程序同时
从多个broker读取和写入数据,当一个新事件发布到一个主题时,它实际上时附加到主题的分区之一。具有相同事件键的事件被写入同一个分区。并且kafka保证给定
主题分区的任何消费者将始终以与写入事件完全相同的顺序读取该分区的事件

消费者组:由多个consumer组成,消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个组内消费者消费(组中一个消费者消费,组里面别的消费者不行),消费者组之间互不影响
partition:为了实现扩展性,一个非常大的topic可以分布到多个broker上,一个topic可以分布到多个broker中,一个topic可以氛围多个partition,每个partition是一个有序队列
replica:副本,为了保证集群中某个节点发生故障,该节点的partition数据不会丢失,一个topic的每个分区都有若干个副本,一个leader和若干个follower
leader:每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数据的对象都是leader。
follower:每个分区多个副本中的“从”,实时从leader中同步数据,保持和leader数据的同步。leader发生故障时,某个follower会成为新的leader。

拦截器:主要用于实现clients端的定制化控制逻辑,它可以使的用户在消息发送前以及producer回调逻辑前有机会对消息做出一些定制化需求,比如修改消息等,同时允许
指定多个interceptor按序作用于同一调消息从而形成一个拦截器链。
拦截器需要实现ProducerInterceptor接口:具体方法解释
configure:做一些初始化工作
onsend:运行在用户的main线程中,producer确保在消息被序列化以计算分区前调用该方法。用户可以在该方法中对消息做任何操作,但最好不要修改所属的topic和分区,否则会
影响目标分区计算。
onAcknowledgement:该方法会在消息被应答之前或消息发送失败时调用,并且通常都是回调逻辑触发之前,该方法运行在producer的I/O线程中,因此不要在该方法中放入很重的
逻辑,否则会拖慢producer的消息发送效率
close:主要执行一些资源清理工作
Interceptor可能运行在多个线程中,因此在具体实现时用户需
要自行确保线程安全。另外,若指定了多个Interceptor,则
producer将按照指定顺序调用它们,同时把每个Interceptor中捕获的异常记录写入到错误日志中而不是向上传递。这在使用过程中要特别留意。

分区优势:1.便以合理使用存储资源,每个partition在一个broker上存储,可以把海量的数据按照分区切割成一块一块数据存储在多台broker上
合理控制分区的任务,可以实现负载均衡的效果
2.提高并行度,生产者可以以分区为单位发送数据,消费者可以以分区为单位进行消费数据
3.分区后,更方便于做副本备份,提高数据安全性
分区原则一:指明partition的情况下,直接将指定的值作为分区值,例如partition=1,对应数据就如分区1
分区原则二:没有具体的partition值而有key的情况下,消息要被发送到的目标分区号partition=Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions
分区原则三:既没有partition值也没有key的情况下,Kafka采用stickyPartitionCache.partition(topic, cluster) 黏性分区器,会随机选择一个分区,
并尽可能一直使用该分区,待该分区的batch已满或linger.ms设置的时间到了,再随机一个分区进行使用(通常和上一次的分区不同)。

自定义分区器:
一:
1.实现接口Partitioner
2.覆盖接口中的方法,主要分区逻辑在方法partition中完成
二:
在用于构造kafkaproducer的peoperties对象中设置partitioner.class参数

消息无丢失
acks:0生产者发送过来的数据,不需要等leader数据持久化就应答完成。数据可靠性最低,丢失数据概率较高,数据就丢失情景:leader未持久化down掉,使用最少
acks:1生产者发送过来的数据,leader收到持久化后应答完成。数据可靠性中等,丢失数据概率中等。丢失数据情景:leader持久化后,所有的follower还没同步数据,
leader挂了。用于传输普通日志。
acks:-1或all 生产者发送过来的数据,leader和isp队列里面的所有节点都持久化数据后才应答。数据可靠性最高,不会丢失数据。传输重要数据,比如和钱相关的数据
思考:在acks=-1或all的情况下,Leader接收到数据并持久化后,所有Follower开始同步Leader刚刚持久化的数据,但是有一个Follower因故障迟迟不能进行数据同步,该问题应该怎么解决?
解决方案:
Leader维护了一个动态的 in-sync replica set(ISR) ,意为和Leader保
持同步的Follower+Leader集合(leader:0,isr:0,1,2)。如果Follower长时间未向Leader发送通信请求或同步数据,则该
Follower将被踢出ISR。该时间阈值由replica.lag.time.max.ms参数设定,默认30000ms。例如1超时,(leader:0, isr:0,2)。这样就不用等长期联系不上或者已经故障的节点。
数据完全可靠性条件:
1ACK级别设置为-1
2分区副本>=2
3ISR应答的最小副本数>=2 (最小副本数有min.insync.replicas设置,默认为1)
生成者中配置响应级别:
// 设置 acks
prop.put(ProducerConfig.ACKS_CONFIG, “all”);
//重试次数 retries,默认是 int 最大值,2147483647
prop.put(ProducerConfig.RETRIES_CONFIG, 3);

消息去重
至少一次(At Least Once):ACK级别设置为-1 + 分区副本
大于等于2 + ISR里应答的最小副本数量大于等于2最多一次(At Most Once):ACK级别设置为0
精确一次(Exactly Once):对于一些非常重要的信息,比如和钱相关的数据,要求数据既不能重复也不丢失。
Kafka 0.11版本以后,引入了一项重大特性:幂等性和事务。
1.At Least Once可以保证数据不丢失,但是不能保证数据不重复;
2.At Most Once可以保证数据不重复,但是不能保证数据不丢失。
生产者_ 数据去重_幂等性
幂等性就是指producer不论向broker发送多少次重复数据,broker都只会持久化一条,保证了不重复
精确一次(Exactly Once) = 幂等性 + 至少一次( ack=-1 +分区副本数>=2 + ISR最小副本数量>=2) 。
重复数据的判断标准:具有<PID, Partition, SeqNumber>相同主键的消息提交时,Broker只会持久化一条。其中PID是Kafka每次重启都会分配一个新的;Partition 表示分区号;Sequence
Number是单调自增的。所以幂等性只能保证的是在单分区单会话内不重复。
如何使用幂等性?
开启参数 enable.idempotence 默认为 true,false 关闭。
生产者_ 数据去重_事务

消费者
消费者有两种消费方式:
push推:模式很难适应消费速率不同的消费者,因为消息发送速率是由broker决定的,它的目标是尽可能以最快速度传递消息,但是这样很容易造成consumer来不及处理消息,具体表现就是
决绝服务以及网络拥塞
consumer采用pull模式从broker中读取数据,pull模式则可以根据consumer的消费能力以适当的速率消费消息。pull模式不足之处是,如果kafka没有数据,消费者可能会陷入循环中,一致返回
空数据,针对这一点,kafka消费者在消费数据时会传入一个时长参数timeout,如果当前没有数据可消费,consumer会等待一段时间之后在返回,这段时长就是timeout
offser刨析
每个消费者的offset由消费者提交到kafka系统主题_consumer_offsets.
__consumer_offsets 主题里面采用 key 和 value 的方式存储数据。key 是 group.id+topic名称+分区号,value 就是当前 offset 的值。
每隔一段时间,kafka 内部会对这个 topic 进行compact,也就是每个 group.id+topic名称+分区号就保留最新数据。
手动提交offset的方法有两种方式:
commitSync 同步提交:必须等待offset提交完毕,再去消费下一批数据。
commitAsync 异步提交:发送完提交offset请求后,就开始消费下一批数据了。
两者的区别:
相同点是,都会将本次消费的一批数据的最高的偏移量提交;
不同点是,同步提交阻塞当前线程,一直到提交成功,并且会自动失败重试(由不可控因素导致,也会出现提交失败);而异步提交则没有失败重试机制,故有可能提交失败。

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值