kafka技术总结

1.kafka基本概念

topic:一个topic可以认为是一类消息。生产者发消息之前都需要设置topic。

producers:将消息写入到kakfa服务端的称之为生产者。producers将消息发布到指定的Topic中,同producer也能决定将此消息归属于哪个partition。

Broker:一个独立的Kafka服务器被称为broker,所有的broker组成一个kafka集群。

customer:将消息从kakfa服务端取出使用的称之为消费者。一个消费者可以读取多个分区的消息。一个分区的消息只能被一个消费者群组的一个消费者读取。如果一个主题有4个分区,我们最多可设置4个消费者来读取消息,多的消费者会被闲置。

customer group:消费者群组,每个消费者属于一个消费者群组。多个消费者群组都可以读取到所有的消息,之间互不影响。

partition:每个topic可以分为多个分区,存储到集群的不同节点,同时可以设置副本的个数来达到可容错的效果。

分区副本:为了保证在个别节点失效的时候能保证kafka的可用性,主题的分区都有对应的副本存在,在首领副本不可用的情况下,跟随者副本被选择为首领副本来处理消息。

偏移量:偏移量是一个不断递增的整数值,消费者通过检查消息的偏移量来区分已经读过的 消息。保存在zookeeper或者kafka上。保证如果消费关闭或者重启,它的读取状态不会丢失。

zookeeper:kafka依赖于zookeeper,保存broker,主题和分区的信息。

序列化器:生产者发送消费到kafka,消费会从网络上传输,必须把消息序列化(消息变成二进制码)后才可以发送消息。kafka默认提供StringSerializer,IntegerSerializer等序列化和反序列化器。我们也可以实现自己的序列化和反序列化器。

分区器:来规定消息发送到哪个分区,如果发送消费的键值为null,使用默认轮询的分区器,消费会被均衡的分布到各个分区上。如果键值不为空,kafka会对键取hash值然后根据散列值把消息映射到特定的分区。同一个键总被映射到同一个分区上。当然我们可以自定义分区器,按照自己的规定特定的消费发送到哪个分区。       

2.kafka架构图 

我们对着下面的架构图来理解下kafka发送消息和消费消息的整个流程。多个producer发送消息,发送消息之前通过分区器选择发送的消息分区,通过序列化器序列化消息,发送到kafka broker上,多个消费者接受消息,接受到消息后,通过反序列化器得到消息内容进行消费,整个流程比较简单。zookeeper保存borker,主题,分区等信息。另外如果有另外的消费者群组来消费消息,这几个消费者群组都可以消费到所有的消息,消费者群组之间互不影响。

3.kafka几个关键配置

kafka broker,生产者,消费者有很多配置,下面简单介绍三个,更多的配置可以查官网。

broker配置

num.partitions :分区数量配置,新创建的主题包含分区的数量。我们也可以针对某一个主题设置分区数量。一个主题该选择多少个分区,我们后续讨论一下。

log.retention.ms:消息数据保存多久,过了这个时间的消息会被删除,如果服务器硬盘不多,业务对消息的实时性要求比较高,可以设置短一点。

log.retention.bytes:一个分区上,主题保存消息的最大字节数,超过这个字节数的时候会删除过期的消息。

default.replication.factor:分区复制系数,一个分区有多少个副本。越大可用性越高,占用存储硬件越多。

生产者配置

acks:指定必须要有多少个分区副本收到消息,生成者才会认为消息写入是成功的。acks越小消息的处理速度越快,消息丢失的概率越大。

retries:发送错误时重新发送消息的次数。临时性的错误(分区找不到首领)重试可解决。我们可以只关注不可重试的错误。

4.kafka常见问题

分区分配原则

一个broker可以放多个分区,那分区分配的原则是什么?

1.broker之间平均分配分区。

2.每个分区的每个副本不能分布在同一个broker上。

3.如果指定了机架信息,每个分区的副本不能分布在同一个机架的broker上。

分区分配算法,假设我们有6个brokers,我们需要分配10个分区的主题,复制系数设置为3

无机架信息:随机选择一个broker3,首领分区0分配在broker3上,首领分区1就分配在broker4上,首领分区2就分配在broker5上,依次类推。分区0首领分配在broker3上,它的一个副本就分配在broker4上,另一个分配在broker5上,其他分区依次类推。

有机架信息:假设broker1,2,3在第一个机架上,broker4,5,6在第二个机架上,那个broker的选择顺序就变为0,3,1,4,2,5。首领分区0分配在broker3上,首领分区1就在broker2上,依次类推,分区0首领分配broker3上,它的第一个副本就在broker1上,它的另一个副本就在broker4上,其他分区依次类推。

如何选定分区数量

选定分区数量之前,你需要考虑几个问题:

1.主题需要多大的吞吐量

2.消费者的吞吐量

3.一个broker能支持多少个分区,broker分区太多占用内存就越多,效率会越低

考虑完成后,比如你主题每秒要读取和写入1GB的数据,每个消费者每秒可以消费50MB,那么至少需要20分区。

消费者提交偏移量的方式 

某个消费者崩溃,或者新的消费加入消费者群组,就会触发再均衡,再均衡后,消费者可能就不是消费自己上一个分区,通过消费者提交的偏移量来确定消费的位置。

1.如果提交的偏移量小于客户端最后处理的偏移量,消息会重复消费。

2.如果提交的偏移量大于客户端最后处理的偏移量,消息会丢失。

偏移量提交方式:

1.自动提交,消费者默认每5秒提交偏移量。

2.同步提交当前偏移量,开发者处理某一个批次的消息后提交偏移量。

3.异步提交当前的偏移量。

4.同步异步组合提交。

上面几种方式都不能完全的解决消费重复和消息丢失的问题,因为消费poll取消息每次取一批消息,如果消费者消费了一半消息后崩溃了,这一批消息就会重复消费。解决的方式是更加频繁的提交,每处理一条消息提交一次偏移量,kafka允许提交特定的偏移量。

kafka效率高的原因

1.顺序写入 

因为硬盘是机械结构,每次读写都会寻址->写入,其中寻址是一个“机械动作”,它是最耗时的。所以硬盘最“讨厌”随机I/O,最喜欢顺序I/O。为了提高读写硬盘的速度,Kafka就是使用顺序I/O。如果一个topic建立多个分区那么每个parathion都是一个文文件,收到消息后Kafka会把数据插入到文件末尾。

2.Kafka使用零拷贝技术  

传统发送网络消息流程:磁盘文件 -> 内核空间的页面缓存 -> 用户空间缓冲区 -> socket缓冲区 -> 网络通道

kafka零拷贝技术:磁盘文件 -> 内核空间的页面缓存 -> 网络通道

3.Kafka的TPS跑到单机百万,主要是由于Producer端将多个小消息合并,批量发向Broker。

分区再均衡

消费者会不停的发送心跳给群组协调器的broker,根据心态可以判断是否有新的消费者加入和旧的消费者是否崩溃,当有新的消费者加入或者旧的消费者崩溃会触发分区再均衡,分区分配策略有以下两种方式:

1.RangeAssignor分配策略
RangeAssignor策略的原理是按照消费者总数和分区总数进行整除运算来获得一个跨度,然后将分区按照跨度进行平均分配,以保证分区尽可能均匀地分配给所有的消费者。对于每一个topic,RangeAssignor策略会将消费组内所有订阅这个topic的消费者按照名称的字典序排序,然后为每个消费者划分固定的分区范围,如果不够平均分配,那么字典序靠前的消费者会被多分配一个分区。

假设n=分区数/消费者数量,m=分区数%消费者数量,那么前m个消费者每个分配n+1个分区,后面的(消费者数量-m)个消费者每个分配n个分区。

2.RoundRobinAssignor分配策略

RoundRobinAssignor策略的原理是将消费组内所有消费者以及消费者所订阅的所有topic的partition按照字典序排序,然后通过轮询方式逐个将分区以此分配给每个消费者。

如何保证消息顺序

1.发送主题的时候加上键值,保证同一个键值的消息被发送到同一个分区。kafka可以保证同一个分区的消息是有序的。

2.max.in.flight.requests.per.connection设置为1,这个配置指定了生产者在收到服务器响应之前可以发送多少个消息。

保证消息顺序会严重影响生产者的吞吐量。

如何保证不重复消费消息,不丢失消息

我们从三个方面来分析怎么实现保证kafka怎么实现不重复消费消息也不丢失消息。

1.broker配置(kafka集群自己的可靠性保障)

default.replication.factor 分区复制系数,如果分区复制系数为1,一个broker崩溃了,该broker里面的分区当然就不存在了,分区里面的消息也就都丢失了,所以分区复制系数至少大于1,最好设为3,如果条件允许可设置为5。

unclean.leader.election 不完全的首领选举,副本会不断的从首领这里复制消息,能正常复制的叫同步副本,不能正常复制的叫非同步副本,这个参数意思是如果首领崩溃了,是否可以从非同步副本选择一个当做首领,如果要保证消息不丢失,这个参数需要设置为false,当然kafka的可用性就会降低。

min.insync.replicas 最少同步副本,生产者想kafka写入消息的时候,如果这个参数设置为2,表示至少一个同步副本和一个首领,kafka才会保存消息,不然就返回异常。如果要保证消息不丢失,这个参数至少设置为2。

2.生产者配置

acks 发送确认,这个参数表示多少个同步副本接收到消息才叫生产者发送消息成功。如果要保证消息不丢失,acks至少大于2。

retries 消息重试,碰见可重试错误时(比如网络波动),生产者自动重试消息。不过消息重试可能会导致消息重复消费,如果消息是幂等的则无所谓,如果不是幂等的,可以为每个消息加上一个唯一的标识符,用于消费者检测重复消息或者利用关系型数据库,键值存储引擎的唯一键特性。

3.消费者配置

在提交偏移量上做文章,每处理一条消息提交一次偏移量。利用关系型数据库将消息处理和提交偏移量放在同一个事务里。读取数据的时候通过seek()方法从该偏移量的位置继续读取数据。

总结一下,保证消息不丢失,需要从broker,生产者,消费者三个方面配合实现,要保证消息不重复,需要结合事务模型或唯一键特性的外部存储系统。                                                                                                                                                                   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值