很多人都说: MQ通过搞消息的发送和接收分高来实现应用程序的异步和解偶,这个给人的直觉是—MQ是异步的,用来解耦的,但是这个只是MQ的效果而不是目的. MQ真正的目的是为了通讯,屏蔽在层复杂的通讯协议定义了一套应用层的、更加简单的通讯协议,MQ 所要做的就是在底层协议上构建一个简单的生产者消费者模型,然后提供一个 SDK 给我们可以定义自己的生产者和消费者实现消息通讯和无视底层通讯协议。
什么是 Kafka号称全球100强的80%的企业都在用,包括制造业,银行,保险,通讯的大公司
Apache Kafka是一个开源的分布式事件流平台,被数千家公司用于高性能数据管道、流分析、数据集成和任务关键型应用程序。
与其他的 MQ 的一些区别- 重 Topic, Topic 是主题的意思,也就是我一个 Broken 里面有多个 Topic ,不同的 Topic 中是收不到消息的,Kafka 非常重视这种模式
- 有 Broken ,那什么是无 Broken 呢,就是在生产者和消费者之间用一个类似 Socket 的方式进行传输,就不需要 Broken 了。
- 多生产者消费者,也就是组的概念
- 基于磁盘的数据存储
- 伸缩性和高性能
- 消息队列
- 日志收集
- 用户活动跟踪
- 流式处理:分布式,高吞吐量,速度快
(1)ZooKeeper:Zookeeper 负责保存 broker 集群元数据,并对控制器进行选举等 *** 作。
(2)Producer:生产者负责创建消息,将消息发送到 Broker。
(3)Broker: 一个独立的 Kafka 服务器被称作 broker,broker 负责接收来自生产者的消息,为消息设置偏移量,并将消息存储在磁盘。broker 为消费者提供服务,对读取分区的请求作出响应,返回已经提交到磁盘上的消息。
(4)Consumer:消费者负责从 Broker 订阅并消费消息。
(5)Consumer Group:Consumer Group 为消费者组,一个消费者组可以包含一个或多个 Consumer 。
使用 多分区 + 多消费者 方式可以极大
提高数据下游的处理速度,同一消费者组中的消费者不会重复消费消息,同样的,不同消费组中的消费者消费消息时互不影响。Kafka 就是通过消费者组的方式来实现消息 P2P 模式和广播模式。
(6)Topic:Kafka 中的消息 以 Topic 为单位进行划分,生产者将消息发送到特定的 Topic,而消费者负责订阅 Topic 的消息并进行消费。
(7)Partition:物理上的概念,一个topic可以分为多个partition,每个partition内部是有序的。同一个主题下不同分区包含的消息是不同的,分区在存储层面可以看作一个可追加的 日志(Log)文件,消息在被追加到分区日志文件的时候都会分配一个特定的 偏移量(offset)。
(8)Offset:offset 是消息在分区中的唯一标识,Kafka 通过它来保证消息在分区内的顺序性*,不过 offset 并不跨越分区,也就是说,Kafka保证的是分区有序性而不是主题有序性。
-
生产者:通过分区的 leader 副本负责数据以先进先出的顺序写入,来保证消息顺序性。
-
消费者:同一个分区内的消息只能被一个 group 里的一个消费者消费,保证分区内消费有序。
-
Kafka 每个 partition 中的消息在写入时都是有序的,消费时, 每个 partition 只能被每一个消费者组中的一个消费者消费,保证了消费时也是有序的。
-
在多生产者多消费者情况下,整个 kafka 不保证有序。如果为了保证 kafka 全局有序,那么只能有一个生产者,一个分区,一个消费者。
在防止消息丢失的方案中,如果生产者发送完消息后,由于网络问题,没有收到 Broken 的ack确认报文,那么它会重新发送,所以这个时候就会有两条相同的消息被消费者重复消费到。
- 生产者关闭重试,但是会造成消息丢失
- 消费者解决幂等性问题:
- 数据库中以唯一性主键,防止相同主键创建多条记录
- 使用分布式锁以业务 id 为锁,比如 Redis ,ZK
Kafka 的存储机制幂等性的特点是其任意多次执行所产生的影响均与一次执行的影响相同,也就是不管你调用这个接口多少次,数据都不会发生改变
- 第一步就是根据 offset 先找到对应的 segment 文件(通过文件名查找)
- 第二部就是通过索引找到某一个具体的消息,也即是通过 index 文件去查到具体的 offset
Kafka 如何做到高吞吐量和高性能 1、页缓存这套机制是建立在offset为有序的基础上,利用 segment +有序offset+稀疏索引+二分查找+顺序查找
等多种手段来高效的查找数据!
Kafka是基于 *** 作系统的页缓存来实现文件写入的。
*** 作系统本身有一层缓存,叫做page cache,是在内存里的缓存,我们也可以称之为os cache,意思就是 *** 作系统自己管理的缓存。
Kafka在写入磁盘文件的时候,可以直接写入这个os cache里,也就是仅仅写入内存中,接下来由** *** 作系统自己决定什么时候把os cache里的数据真的刷入磁盘文件中,所以就是在写内存而不是写磁盘。
**
kafka写数据的时候,是以磁盘顺序写的方式来写的。也就是说,仅仅将数据追加到文件的末尾,不是在文件的随机位置来修改数据。也就是 append only 。
普通的机械磁盘如果你要是随机写的话,确实性能极差,也就是随便找到文件的某个位置来写数据。
但是如果你是追加文件末尾按照顺序的方式来写数据的话,那么这种磁盘顺序写的性能基本上可以跟写内存的性能相差无几。
在 *** 作系统看来两个逻辑上连续的扇区(sector)未必在物理上就是连续的,因为读写都是物理地址映射出的基于虚拟地址,而现代 *** 作系统基本都使用main memory为需要写的data做cache,使用 “append only” 的方法,能够尽可能的使得要写的内容在物理上连续,从而读的时候也是一个顺序读
根据kafka官网的说法,6个7200转的磁盘组成raid5,顺序写的速度能达到(600MB/S),而随机读写速度仅为100kb/s
基于上面两点, kafka就实现了写入数据的超高性能。
3、零拷贝
一次是从 *** 作系统的 cache 里拷贝到应用进程的缓存里,接着又从应用程序缓存里拷贝回 *** 作系统的 Socket 缓存里。
而且为了进行这两次拷贝,中间还发生了好几次上下文切换,一会儿是应用程序在执行,一会儿上下文切换到 *** 作系统来执行。所以这种方式来读取数据是比较消耗性能的。
Kafka 为了解决这个问题,在读数据的时候是引入零拷贝技术也就是说,直接让 *** 作系统的 cache 中的数据发送到网卡后传输给下游的消费者,中间跳过了两次拷贝数据的步骤,Socket 缓存中仅仅会拷贝一个描述符过去,不会拷贝数据到 Socket 缓存
那 Kafka 是如何保障它的可靠性的呢Linux 中一切皆为文件
- 在引入消费者组的情况下,保证同一个消费者组中不会有两个消费者消费同一个 Topic
- 虽然是通过内存做的零拷贝,但是数据也是会落到磁盘中,保证数据的可靠性
- 有主从的概念,消费者从主服务器中拉取消息,从服务器只做备份
副本是相对partition而言的,一个分区中包含一个或多个副本,其中一个为 leader副本,其余为follower副本,各个副本位于不同的broker节点中。所有的读写 *** 作都是经过Leader进行的,同时follower会定期地去leader上复制数据。
当Leader挂掉之后,其中一个follower会重新成为新的Leader.通过分区副本,引入了数据冗余,同时也提供了Kafka的数据可靠性
ISR机制Kafka的分区多副本架构是Kafka可靠性保证的核心,把消息写入多个副本可以使Kafka在发生崩溃时仍能保证消息的持久性。
在分区中,所有副本统称为AR, Leader维护了一个动态的in-sync
replica(ISR),ISR是指与leader副本保持同步状态的副本集合。当然leader副本本身也是这个集合中的一员。
当ISR中的follower完成数据同步之后, leader就会给follower发送ack,如果其中一个follower长时间未向leader同步数据,该follower将会被踢出ISR集合,当leader发生故障后,就会从ISR集合中重新选举出新的leader
ack应答机制为保证producer发送的数据,能可靠的达到指定的topic,Producer提供了消息确认机制。生产者往Broker的topic中发送消息时,可以通过配置来决定有几个副本收到这条消息才算消息发送成功。可以在定义Producer时通过acks参数指定,这个参数支持以下三种值:
(1) acks=0: producer不会等待任何来自broker的响应特点:低延迟,高吞吐,数据可能会丢失。
如果当中出现问题,导致broker没有收到消息,那么producer无从得知,会造成消息丢失。
(2) acks=1 (默认值) :只要集群中partition的Leader节点收到消息,生产者就会收到一个来自服务器的成功响应。
如果在follower同步之前, leader出现故障,将会丢失数据。
(3) acks–1:只有当所有参与复制的节点全部都收到消息时,生产者才会收到一个来自服务器的成功响应。
这种模式是最安全的,可以保证不止一个服务器收到消息,就算有服务器发生崩溃,整个集群依然可以运行。
根据实际的应用场景,选择设置不同的acks,以此保证数据的可靠性。
总结 高性能:零拷贝,磁盘顺序读写 高可靠:多副本,应答机制,存储机制 高吞吐量:磁盘存储,数据传输Producer发送消息还可以选择同步或异步模式,如果设置成异步,虽然会极大的提高消息发送的性能,但是这样会增加丢失数据的风险。如果需要确保消息的可靠性,必须将 producer.type 设置为sync.
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)