小厂后端十连问(附答案)(二)
8、kafka是如何保证消息的有序性?
kafka这样保证消息有序性的:
• 一个 topic,一个 partition,一个 consumer,内部单线程消费,单线程吞吐量太低,一般不会用这个。(全局有序性)
• 写 N 个内存 queue,具有相同 key 的数据都到同一个内存 queue;然后对于 N 个线程,每个线程分别消费一个内存 queue 即可,这样就能保证顺序性。
大家可以看下消息队列的有序性是怎么推导的哈:
消息的有序性,就是指可以按照消息的发送顺序来消费。有些业务对消息的顺序是有要求的,比如先下单再付款,最后再完成订单,这样等。假设生产者先后产生了两条消息,分别是下单消息(M1),付款消息(M2),M1比M2先产生,如何保证M1比M2先被消费呢。为了保证消息的顺序性,可以将将M1、M2发送到同一个Server上,当M1发送完收到ack后,M2再发送。如图:这样还是可能会有问题,因为从MQ服务器到服务端,可能存在网络延迟,虽然M1先发送,但是它比M2晚到。那还能怎么办才能保证消息的顺序性呢?将M1和M2发往同一个消费者,且发送M1后,等到消费端ACK成功后,才发送M2就得了。消息队列保证顺序性整体思路就是这样啦。比如Kafka的全局有序消息,就是这种思想的体现: 就是生产者发消息时,1个Topic只能对应1个Partition,一个 Consumer,内部单线程消费。
但是这样吞吐量太低,一般保证消息局部有序即可。在发消息的时候指定Partition Key,Kafka对其进行Hash计算,根据计算结果决定放入哪个Partition。这样Partition Key相同的消息会放在同一个Partition。然后多消费者单线程消费指定的Partition。
9、Nacos的选举机制了解嘛?说下Raft算法?
Nacos作为配置中心的功能是基于Raft算法来实现的。
Raft 算法是分布式系统开发首选的共识算法,它通过“一切以领导者为准”的方式,实现一系列值的共识和各节点日志的一致。
Raft选举过程涉及三种角色和任期(Term):
• Follower:默默地接收和处理来自Leader的消息,当等待Leader心跳信息超时的时候,就主动站出来,推荐自己当Candidate。
• Candidate:向其他节点发送投票请求,通知其他节点来投票,如果赢得了大多数(N/2+1)选票,就晋升Leader。
• Leader:负责处理客户端请求,进行日志复制等操作,每一轮选举的目标就是选出一个领导者;领导者会不断地发送心跳信息,通知其他节点“我是领导者,我还活着,你们不要发起新的选举,不用找个新领导者来替代我。”
• Term:这跟民主社会的选举很像,每一届新的履职期称之为一届任期
领导选举过程
1.在初始时,集群中所有的节点都是Follower状态,都被设定一个随机选举超时时间(一般150ms-300ms):
2.如果Follower在规定的超时时间,都没有收到来自Leader的心跳,它就发起选举:将自己的状态切为 Candidate,增加自己的任期编号,然后向集群中的其它Follower节点发送请求,询问其是否选举自己成为Leader:
3.其他节点收到候选人A的请求投票消息后,如果在编号为1的这届任期内还没有进行过投票,那么它将把选票投给节点A,并增加自己的任期编号:
4.当收到来自集群中过半节点的接受投票后,A节点即成为本届任期内 Leader,他将周期性地发送心跳消息,通知其他节点我是Leader,阻止Follower发起新的选举:
10、聊一聊TCC补偿机制
TCC是分布式事务的一种解决方案。它采用了补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。TCC(Try-Confirm-Cancel)包括三段流程:
• try阶段:尝试去执行,完成所有业务的一致性检查,预留必须的业务资源。
• Confirm阶段:该阶段对业务进行确认提交,不做任何检查,因为try阶段已经检查过了,默认Confirm阶段是不会出错的。
• Cancel 阶段:若业务执行失败,则进入该阶段,它会释放try阶段占用的所有业务资源,并回滚Confirm阶段执行的所有操作。
下面再拿用户下单购买礼物作为例子来模拟TCC实现分布式事务的过程:
假设用户A余额为100金币,拥有的礼物为5朵。A花了10个金币,下订单,购买10朵玫瑰。余额、订单、礼物都在不同数据库。
TCC的Try阶段:
• 生成一条订单记录,订单状态为待确认。
• 将用户A的账户金币中余额更新为90,冻结金币为10(预留业务资源)
• 将用户的礼物数量为5,预增加数量为10。
• Try成功之后,便进入Confirm阶段
• Try过程发生任何异常,均进入Cancel阶段
TCC的Confirm阶段:
• 订单状态更新为已支付
• 更新用户余额为90,可冻结为0
• 用户礼物数量更新为15,预增加为0
• Confirm过程发生任何异常,均进入Cancel阶段
• Confirm过程执行成功,则该事务结束
TCC的Cancel阶段:
• 修改订单状态为已取消
• 更新用户余额回100
• 更新用户礼物数量为5
• TCC的优点是可以自定义数据库操作的粒度,降低了锁冲突,可以提升性能
• TCC的缺点是应用侵入性强,需要根据网络、系统故障等不同失败原因实现不同的回滚策略,实现难度大,一般借助TCC开源框架,ByteTCC,TCC-transaction等。
最后
感谢大家能看到这里,愿大家都能找到理想的offer!有兴趣讨论技术,分享大厂面试真题、内推、上班摸鱼的小伙伴,可以加我微信,备注加群哈。下篇文章,我们再见~