分布式理论和Kafka

	1)分布式
	多个子服务间远程调用协调工作,
	中心化 (k8s)。
	去中心化:有领导,只是由节点自由选取。 
	脑裂:由于网络原因,形成了两个单独的集群各自工作,严重数据冲突,解决办法:小的集群全员自杀。

	CAP:一致性、可用性(不保证是最新数据) 、分区容错性(某网络分区出错时,仍提供一致性可用性服务,除非整个网络坏了),P一定要,3个不能同时满足,不是3选2,CA可以互相妥协 -- > BASE理论:基本可用(查询时间0.5->2或降级页面)、软状态、最终一致性。

	a b两个数据库,一样的数据,a更新了数据,未同步到b,a死了,查询请求来了b,两个选择: 1.返回老数据 (可用性) 2.等a好了后同步a再返回新数据(一致性)。

	分布式事务:下面这段可参考下:[2pc](https://blog.csdn.net/weixin_44335140/article/details/110762850)
	关注点:协调者、参与者、事务是否真正提交。
	2pc:1、参与者执行事务内容,协等响应(YES NO 超时)   2、提交,成功返回ack。  存在的问题:同步阻塞 、单点问题、数据不一致(部分参与者已提交,协死或者参死),过于保守。
	
	3pc:多个第一阶段,询问参与者是否可以提交该事务(事务已经发过去了),2pc没有参与者超时功能,3pc在2阶段完后,3阶段参与者如果超时自动提交。

	Paxos算法:多个节点间确定一个值,client1 set x=3 ,client2 set x=2 都提交一个值,abc三个服务端如何就一个值达成共识,最终只确定一个。提议者、接受者(abc  一般是master)、学习者(slave)。
	1、发提案号AA,之前未通过任何提案,返回无提案,若之前通过,返回已通过的最大提案号的提案信息,承诺之后不再响应<=AA的1过程,不再通过<AA的提案。
	2、客户端在收到大多数响应后,发送提案值,若失败,即响应<=一半,重新生成个提案号重提。
存在活锁问题。

	Raft算法:leader不断向追随者发消息说我还活着,追随者发现leader死后,毛遂自荐,任期编号+1,让其他人投,若得到大多数选票就成功,client直接找领导(最开始没有leader,都有连接leader的超时时间(随机的),谁的先过期谁先毛遂自荐),先来先服务的原则进行投票。
	Leader负责日志复制管理,日志复制为保证每个节点执行相同的操作序列。
	接收client请求(即日志),并复制给其他节点,通知他们提交日志。
	当Leader收到大多数(n/2+1)Follower的ACK信息后,将该日志设置为已提交并追加到本地磁盘中,通知客户端,并在下个heartbeat中,Leader将通知所有的Follower将该日志存储在自己的本地磁盘中。
	安全性是用于保证每个节点都执行相同序列的安全机制,如当某个Follower在当前Leader commit Log时变得不可用了,稍后可能该Follower又会被选举为Leader,这时新Leader可能会用新的Log覆盖先前已committed的Log,这就导致节点执行不同序列;Safety(安全性)就是用于保证选举出来的Leader一定包含先前commited Log的机制。

	2)kafka
	Kafka,消息队列,有一对一,一对多模式(发布到Topic中的消息会被多个消费者消费),我们下面说的全是一对一模式。
	生产者、Kafka集群Broker、消费者、注册消息Zookeeper、消费者组(内含多个消费者,可消费topic下不同分区的消息,某一个分区中的消息只能够一个消费者组中的一个消费者所消费)。
	
	一个非常大的Topic可以分布到多个Broker上,一个Topic可以分为多个Partition,每个分区是一个有序的队列(分区有序,不能保证全局有序),一个Topic的每个分区有若干个副本,一个Leader和多个Follower以Partition为单位进行读写,类似于多路。
	
	Producer生产的数据会被不断的追加到该log文件的末端,且每条数据都有自己的offset,consumer组中的每个consumer,都会实时记录自己消费到了哪个offset,以便出错恢复的时候,可以从上次的位置继续消费。
	
	一个topic有多个分区,每个分区有多个segment ,以1g为分割点,一个segment对应一个.LOG和.INDEX文件
	.LOG是实际内容.index是一个映射,offset -> log文件中多少行,每个.index的offset从0开始,偏移=offset+当前.INDEX文件的名字。
	
	消息的内容是 key和value。 
	
	生产者ISR:为保证producer发送的数据能够可靠的发送到指定的topic中,topic的每个partition收到producer发送的数据后,都需要向producer发送ack,如果producer收到ack就会进行下一轮的发送,否则重新发送数据。
	kafka是全部的follower同步完成,才可以发送ack,但如果有个follower故障咋搞,迟迟不返回,用ISR,如果follower长时间没有向leader同步数据,则该follower将从ISR中被踢出。当leader发生故障之后,会从ISR中选举出新的leader。
	
	Kafka为用户提供了三种可靠性级别,用户根据可靠性和延迟的要求进行权衡选择不同的配置。
	1.broker接收到还没有写入磁盘就已经返回,会数据丢失  At Most Once。
	2.partition的leader落盘成功后返回ack,会数据丢失。
	3.ISR的follower全部落盘成功才返回ack,会数据重复 At Least Once。
	对于重要的数据,则要求数据不重复也不丢失,即Exactly Once。
	
	在0.11版本的Kafka之前,只能保证数据不丢失,在下游对数据的重复进行去重操作,多余多个下游应用的情况,进行全局去重,对性能有很大影响。0.11版本的kafka,引入了一项重大特性:幂等性,幂等性指代Producer不论向Server发送了多少次重复数据,Server端都只会持久化一条数据。

	Kafka的幂等性实现实际是将之前的去重操作放在了数据上游来做,开启幂等性的Producer在初始化的时候会被分配一个PID,发往同一个Partition的消息会附带Sequence Number,而Broker端会对<PID,Partition,SeqNumber>做缓存,当具有相同主键的消息的时候,Broker只会持久化一条。
	
	但PID在重启之后会发生变化,同时不同的Partition也具有不同的主键,所以幂等性无法保证跨分区跨会话的Exactly Once。

	LEO:每个副本最后的一个offset。
	HW:指代消费者能见到的最大的offset,ISR队列中最小的LEO。
	follower故障:follower发生故障后会被临时踢出ISR,等待该follower恢复后,follower会读取本地磁盘记录的上次的HW,并将log文件高于HW的部分截取掉,从HW开始向leader进行同步,等待该follower的LEO大于等于该partition的HW,即follower追上leader之后,就可以重新加入ISR了。
	leader故障:leader发生故障之后,会从ISR中选出一个新的leader,为了保证多个副本之间的数据的一致性,其余的follower会先将各自的log文件高于HW的部分截掉,然后从新的leader中同步数据。
	这只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复。

	由于Consumer在消费过程中可能会出现断电宕机等故障,Consumer恢复以后,需要从故障前的位置继续消费,所以Consumer需要实时记录自己消费到了那个offset,以便故障恢复后继续消费。
	Kafka0.9版本之前,consumer默认将offset保存在zookeeper中,从0.9版本之后,consumer默认将offset保存在kafka一个内置的topic中,该topic为__consumer_offsets。
	如果所有实列属于同一个Group,那么它实现的就是消息队列模型;如果所有实列分别属于不同的Group,那么他实现的就是发布/订阅模型,就是前面说的一对多模式。
	顺序写磁盘、零复制技术:log的文件缓存区->socket缓冲区。

	Kafka集群中有一个broker会被选举为Controller,负责管理集群broker的上下线、所有topic的分区副本分配和leader的选举等工作。Controller的工作管理是依赖于zookeeper的。

	需要引入一个全局唯一的Transaction ID,并将Producer获得的PID和Transaction ID进行绑定,这样当Producer重启之后就可以通过正在进行的Transaction ID获得原来的PID。
	为了管理Transaction,Kafka引入了一个新的组件Transaction Coordinator,Producer就是通过有和Transaction Coordinator交互获得Transaction ID对应的任务状态,Transaction Coordinator还负责将事务信息写入内部的一个Topic中,这样即使整个服务重启,由于事务状态得到保存,进行中的事务状态可以恢复,从而继续进行。

	Kafka的Producer发送消息采用的是异步发送的方式,在消息发送的过程中,设计到了两个线程main线程和Sender线程,以及一个线程共享变量RecordAccumulator,main线程将消息发送给RecordAccumulator,Sender线程不断从RecordAccumulator中拉取消息发送到Kafka broker中。
	BATCH_SIZE_CONFIG = "batch.size":消息为batch.size大小,生产者才发送消息
	LINGER_MS_CONFIG = "linger.ms":如果消息大小迟迟不为batch.size大小,则等待linger.ms时间后直接发送

	消费者提交offset方式: 自动提交(可设间隔时间),手动提交(分为同步和异步)。
	先提交offset后消费,有可能造成数据的漏消费,而先消费再提交offset,有可能会造成数据的重复消费。
	当有新的消费者加入消费者组、已有的消费者退出消费者组或者订阅的主体分区发生了变化,会触发分区的重新分配操作,重新分配的过程称为Rebalance。
	消费者发生Rebalace之后,每个消费者消费的分区就会发生变化,因此消费者需要先获取到重新分配到的分区,并且定位到每个分区最近提交的offset位置继续消费。
	自己记录下需要提交的offset,利用Rebalance分区监听器监听rebalance事件,一旦发生rebalance,先将offset提交,分区之后则找到最新的offset位置继续消费即可。

	拦截器:拦截链interceptor chain,重写方法  onSend(ProducerRecord record),onAcknowledgement(RecordMetadata metadata, Exception exception),分区器Partitioner用来判断消息发送到哪一个分区。序列化器是对数据进行序列化和反序列化。拦截器对于消息发送进行一个提前处理和收尾处理。
  • 16
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

成长是自己的事

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值