小厂后端十连问(附答案)(二)

chujichenxuyuan
发布于 2022-6-29 13:49
浏览
0收藏

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!有兴趣讨论技术,分享大厂面试真题、内推、上班摸鱼的小伙伴,可以加我微信,备注加群哈。下篇文章,我们再见~

标签
已于2022-6-29 13:49:46修改
收藏
回复
举报
回复