我们知道经典的CAP理论中,在p无可避免的情况下,可用性和一致性只能保证一个,那么kafka是ap还是cp的呢?
其实它是可以根据配置所调整的,提到HA,尤其是使用leader选举+多副本机制的,基本上套路也都是类似的,无可避免的,会有三个核心问题的解决。
1.数据的同步问题:
数据是由leader push过去还是有flower pull过来? kafka是由follower周期性或者尝试去pull(拉)过来(其实这个过程与consumer消费过程非常相似),写是都往leader上写,但是读并不是任意flower上读都行,读也只在leader上读,flower只是数据的一个备份,保证leader被挂掉后顶上来,并不往外提供服务。
为什么只提供写不提供读呢?因为kafka的读的状态(offset)是需要在server端维护的,如果说读也从多个副本去读的话,会带来这种读状态维护的复杂性,而且本身根据多个partition做了分区之后,已经能够保证了很好的负载均衡性能。
2.数据何时commit的问题:
这个核心就在于,多少个副本同步了之后,消息才能commit。
kafka里维护了一个叫做ISR的列表,即这个列表中的所有副本与leader的已提交的记录是完全一致的,那么在实际客户端配置的时候,有两点可调控的:
request.required.asks:
0就是说明不需要leader回复就算commit,1,leader必须要同步成功才能返回成功;-1:所有的ISR都同步成功了,才算成功;
可以看出来,如果选择了0,那可用性就很高,但是数据一致性无法保证,一般是不选择这个的,如果选择了1,同样的,可用性很高,但一旦leader宕机,基本数据妥妥的不一致,而如果是-1,那么问题来了,所有的ISR都同步成功,这个ISR究竟是多少个呢?
那么就是第二点可配置的:
min.insync.replicas:
这个就是最低的可用副本数,注意,这个是包含leader本身的,这个数字一般我们设置为2个,即除leader外有一个同步副本即可。
另外,我们思考一个问题,为什么他要用这个副本列表的方式,因为我们知道最常见的leader选举或者这种commit提交的一种做法是少数服从多数的做法,也就是比如说一共7个副本,那只要四个都同意了,剩下三个可以不用管。相比于副本列表而言,这种方式的好处在于,响应最快的四个决定了整个系统的响应速度,而副本列表则限制了必须要等待最慢的那个副本同步完成才算完成;坏处就在于,需要维护更多的副本数,即对于7个副本的系统来说,只能三个副本宕机,而如果是同步列表的话,6个宕机都可以。
3.宕机之后的fail recover问题:
那么恢复的时候,也是,如果你选择从ISR中恢复,那么这个等待时间可能很长,可用性就比较低,而如果选择从任意一个副本恢复,那可用性就高,但是数据一致性就低。
网友评论