之前主要介绍和学习了一些服务端和业务强相关的技术组件和框架,随着业务量的大幅度增加,单一的部署形式越来越不能满足服务的请求,那么业务的扩展就需要服务的增加,但是单纯的水平扩展是不能满足业务需求的,因此微服务就成了大家关注的对象,下面首先介绍下常用的协调系统Kafka:
一、Kafka设计的目的在于:
1、以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间的访问性能
2、高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒100K条消息的传输
3、支持Kafka Server间的消息分区,及分布式消费,同时保证每个partition内的消息顺序传输。
4、同时支持离线数据处理和实时数据处理。
5、Scale out:支持在线水平扩展
二、Kafka的工作方式:
Kafka就是一种发布-订阅模式(这个和celery有点像)
三、优点:
1、解耦:
2、冗余:可靠性------副本
3、扩展性:
4、灵活性:
5、可恢复性
6、顺序保证:
7、缓冲:
8、异步通信:
四:下面看下Kafka的整体结构图:
首先了解下Kafka组件中的基本概念:
1、Producer:
生产者即数据的发布者,该角色将消息发布到Kafka的topic中。broker接收到生产者发送的消息后,broker将该消息追加到当前用于追加数据的segment文件中。生产者发送的消息,存储到一个partition中,生产者也可以指定数据存储的partition。
2、Broker:
Kafka 集群包含一个或多个服务器,服务器节点称为broker。一般可以表述为基于分布式框架zookeeper而hadoop HA集群。
broker存储topic的数据。如果某topic有N个partition,集群有N个broker,那么每个broker存储该topic的一个partition。
如果某topic有N个partition,集群有(N+M)个broker,那么其中有N个broker存储该topic的一个partition,剩下的M个broker不存储该topic的partition数据。
如果某topic有N个partition,集群中broker数目少于N个,那么一个broker存储该topic的一个或多个partition。在实际生产环境中,尽量避免这种情况的发生,这种情况容易导致Kafka集群数据不均衡。
3、Topic:
每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic。(物理上不同Topic的消息分开存储,逻辑上一个Topic的消息虽然保存于一个或多个broker上但用户只需指定消息的Topic即可生产或消费数据而不必关心数据存于何处)
类似于数据库的表名
4、Partition:
topic中的数据分割为一个或多个partition。每个topic至少有一个partition。每个partition中的数据使用多个segment文件存储。partition中的数据是有序的,不同partition间的数据丢失了数据的顺序。如果topic有多个partition,消费数据时就不能保证数据的顺序。在需要严格保证消息的消费顺序的场景下,需要将partition数目设为1
5、Replication:
指Partition的副本,用于备份消息的,这也是Kafka高可用的基础。当消息发送给Partition的leader模块时,follower就会获取消息。
a、Leader:每个partition有多个副本,其中有且仅有一个作为Leader,Leader是当前负责数据的读写的partition。
b、Follower:Follower跟随Leader,所有写请求都通过Leader路由,数据变更会广播给所有Follower,Follower与Leader保持数据同步。如果Leader失效,则从Follower中选举出一个新的Leader。当Follower与Leader挂掉、卡住或者同步太慢,leader会把这个follower从“in sync replicas”(ISR)列表中删除,重新创建一个Follower。
6、Consumer:
消费者可以从broker中读取数据。消费者可以消费多个topic中的数据。
7、Consumer Group:
每个Consumer属于一个特定的Consumer Group(可为每个Consumer指定group name,若不指定group name则属于默认的group)。
五、实现流程:
正常情况会认为一个topic是一个queue,那么对于的consumer就必须逐个进行处理队列里的消息,但实际上Topic会被分为一堆partition,那么多个consumer就可以并行处理topic中的消息,而同一个partition的消息又可以变的有序。
下面来看下相关文件的组成:
在Kafka文件存储中,同一个topic下有多个不同partition,每个partition为一个目录,partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。
那么作为目录的partition下面又有哪些文件呢?答案是segment
segment 是由index file和data file文件组成,此2个文件一一对应,成对出现,后缀".index"和“.log”分别表示为segment索引文件、数据文件,例如下:
segment文件命名规则:partion全局的第一个segment从0开始,后续每个segment文件名为上一个segment文件最后一条消息的offset值。数值最大为64位long大小,19位数字字符长度,没有数字用0填充。
segment中index与data file对应关系物理结构如下:
索引文件存储大量元数据,数据文件存储大量消息,索引文件中元数据指向对应数据文件中message的物理偏移地址。
其中以索引文件中元数据3,497为例,依次在数据文件中表示第3个message(在全局partiton表示第368772个message),以及该消息的物理偏移地址为497
六、Kafka系统的高可用性:
在Kakfa系统中,一旦某一个Broker宕机,则其上所有的Partition数据都不可被消费,这与Kafka数据持久性及Delivery Guarantee的设计目标相悖。为了保证系统的高可用性,副本(Replication)就诞生了,同一个Partition可能会有多个Replica,而这时需要在这些Replication之间选出一个Leader,Producer和Consumer只与这个Leader交互,其它Replica作为Follower从Leader中复制数据。
为了保证数据的一致性和有序性,并要求系统简单,因此就引入了Leader,只有Leader负责数据读写,Follower只向Leader顺序Fetch数据(N条通路),系统更加简单且高效。
Kafka分配Replica的算法如下:
1.将所有Broker(假设共n个Broker)和待分配的Partition排序
2.将第i个Partition分配到第(i mod n)个Broker上
3.将第i个Partition的第j个Replica分配到第((i + j) mode n)个Broker上
那么怎么保证replication的follower上的数据和leader保持一致的呢?当消息发送给partition后,并不立即回响应ACK,而是等有一定数量的follower获取完leader数据后,才会ack进行保证的。而所有的replication对应的信息都是存放在一个叫做ISR(即in-sync Replica)的列表中的,那如果等待所有的follower回ack,那岂不是会放缓系统的处理速度,因此需要一种策略来保证系统既能快速响应又能保证系统消息可靠的被处理,那正常在kafka系统中是这样的策略:假设有2n+1个副本,包括leader,那么只要等到有n个副本从leader上fetch成功即可,也就是保证有n+1个副本上有数据。
下面链接可以看到HA相关ZooKeeper结构:
https://www.cnblogs.com/qingyunzong/p/9004703.html