一个挺着啤酒肚,身穿格子衫,发际线重大后移的中年男子,手拿着保温杯,胳膊夹着MacBook向你走来,看样子是架构师级别。
面试开始,直入正题。
面试官: 我看到你的简历上写着我的项目中用到了音讯队列,还用的是kafka,你有遇到过音讯队列失落音讯的状况吗?
我: [疑难] 音讯队列还能失落音讯?那谁还用音讯队列!你是不是搞错了?我没遇到过失落音讯的状况,也没思考过这个问题。
面试官: 嗯...,小伙子,看来有些面试套路,你还是不太懂。明天面试就先到这里吧!给你的简历,我送你下楼。
我去!面试还有啥套路?
能不能少一点套路,多一点真挚!
难道都要去背一遍八股文能力加入面试?
好吧,我去瞅一眼一灯总结的面试八股文。
我: 音讯队列发送音讯和生产音讯的过程,共分为三段,生产过程、服务端长久化过程、生产过程,如下图所示。
这三个过程都有可能弄丢音讯。
面试官: 嗯,音讯失落的具体起因是什么?怎么避免失落音讯呢?
我: 我具体说一下这种状况:
一、生产过程失落音讯
失落起因:个别可能是网络故障,导致音讯没有发送进来。
解决方案:重发就行了。
因为kafka为了进步性能,采纳了异步发送音讯。咱们只有获取到发送后果,能力确保音讯发送胜利。
有两个计划能够获取发送后果。
一种是kafka把发送后果封装在Future对象中,我能够应用Future的get办法同步阻塞获取后果。
Future<RecordMetadata> future = producer.send(new ProducerRecord<>(topic, message));try { RecordMetadata recordMetadata = future.get(); if (recordMetadata != null) { System.out.println("发送胜利"); }} catch (Exception e) { e.printStackTrace();}
另一种是应用kafka的callback函数获取返回后果。
producer.send(new ProducerRecord<>(topic, message), new Callback() { @Override public void onCompletion(RecordMetadata metadata, Exception exception) { if (exception == null) { System.out.println("发送胜利"); } else { System.out.println("发送失败"); } }});
如果发送失败了,有两种重试计划:
- 手动重试
在catch逻辑或else逻辑中,再调用一次send办法。如果还不胜利怎么办?
在数据库中建一张异样音讯表,把失败音讯存入表中,而后搞个异步工作重试,便于管制重试次数和间隔时间。 主动重试
kafka反对主动重试,设置参数如下,当集群Leader选举中或者Follower数量有余等起因返回失败时,就能够主动重试。# 设置重试次数为3retries = 3# 设置重试距离为100msretry.backoff.ms = 100
个别咱们不会用kafka主动重试,因为超过重试次数,还是会返回失败,还须要咱们手动重试。
二、服务端长久化过程失落音讯
为了保障性能,kafka采纳的是异步刷盘,当咱们发送音讯胜利后,Broker节点在刷盘之前宕机了,就会导致音讯失落。
当然咱们也能够设置刷盘频率:
# 设置每1000条音讯刷一次盘flush.messages = 1000# 设置每秒刷一次盘flush.ms = 1000
先遍及一下kafka集群的架构模型:
kafka集群由多个broker组成,一个broker就是一个节点(机器)。
一个topic有多个partition(分区),每个partition散布在不同的broker下面,能够充分利用分布式机器性能,扩容时只须要加机器、加partition就行了。
一个partition又有多个replica(正本),有一个leader replica(主正本)和多个follower replica(从正本),这样设计是为了保证数据的安全性。
发送音讯和生产音讯都在leader下面,follower负责定时从leader下面拉取音讯,只有follower从leader下面把这条音讯拉取回来,才算生产者发送音讯胜利。
kafka为了放慢长久化音讯的性能,把性能较好的follower组成一个ISR列表(in-sync replica),把性能较差的follower组成一个OSR列表(out-of-sync replica),ISR+OSR=AR(assigned repllicas)。
如果某个follower一段时间没有向leader拉取音讯,落后leader太多,就把它移出ISR,放到OSR之中。
如果某个follower追上了leader,又会把它从新放到ISR之中。
如果leader挂掉,就会从ISR之中选一个follower做leader。
为了晋升长久化音讯性能,咱们能够进行一些设置:
# 如果follower超过一秒没有向leader拉取音讯,就把它移出ISR列表rerplica.lag.time.max.ms = 1000# 如果follower落后leader一千条音讯,就把它移出ISR列表rerplica.lag.max.messages = 1000# 至多保障ISR中有3个followermin.insync.replicas = 3# 异步音讯,不须要leader确认,立刻给生产者返回发送胜利,失落音讯概率较大asks = 0# leader把音讯写入本地日志中,不会等所有follower确认,就给生产者返回发送胜利,小概率失落音讯asks = 1# leader须要所有ISR中follower确认,才给生产者返回发送胜利,不会失落音讯asks = -1 或者 asks = all
三、生产过程失落音讯
kafka中有个offset的概念,consumer从partition中拉取音讯,consumer本地解决实现后须要commit一下offset,示意生产实现,下次就不会再拉取到这条音讯。
所以咱们须要敞开主动commit offset的配置,避免consumer拉到音讯后,服务宕机,导致音讯失落。
enable.auto.commit = false
面试官: 还得是你,就你总结的全,我都想不那么全,今天来下班吧,薪资double。
本文知识点总结:
文章继续更新,能够微信搜一搜「 一灯架构 」第一工夫浏览更多技术干货。