博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Kafka如何做到高可用及保证写入数据不丢失
阅读量:2154 次
发布时间:2019-05-01

本文共 2858 字,大约阅读时间需要 9 分钟。

Kafka如何做到高吞吐低延迟的高并发高性能

  1. 页缓存+磁盘顺序写。首先kafka是基于操作系统的页缓存(page cache)来实现写入文件,写入的时候先往页缓存中写,基于内存,性能非常好,然后由操作系统自己决定何时把数据写入磁盘,写磁盘是按追加在文件结尾顺序写的方式,这样性能也非常好
  2. 零拷贝技术。读数据的时候,会先看操作系统中的cache中是否存在,存在的话直接让操作系统中cache的数据发送到网卡后传输给消费者,不会拷贝数据到socket缓存。

Kafka如何保证写入数据不丢失

  1. 分布式存储架构。kafka有个核心概念叫topic,可以理解为一个数据集合,还有个概念叫Partition,也就是把数据集合拆分为多个数据分区,每个Partition 可以分别存放在不同机器上存储部分数据。
  2. 为保证数据不丢失,数据需要做多副本存放,kafka会选举其中一个Partition 副本作为Leader,其他副本作为Follower,只有Leader 是对外提供读写数据,Follower只是从Leader 同步数据。当Leader宕机时,kafka会重新选举出一个副本作为Leader 对外提供读写服务,从而实现高可用架构
  3. 写入丢失问题,当数据写入leader,还没有同步到Follower时,leader宕机,会造成数据丢失。
  4. ISR机制(“In-Sync Replicas”)。kafka会⾃动给每个 Partition 维护⼀个 ISR 列表,这个列表⾥⼀定会有 Leader,然后还会包含跟 Leader 保持同步的Follower。如果某个Follower因为自身的问题不能及时和Leader 同步数据,那么这个Follower就会被认为是“out-of-sync”,从 ISR 列表⾥踢出去。ISR机制就是 Kafka ⾃动维护和监控哪些 Follower 及时的 跟上了 Leader 的数据同步。
  5. 如果要保证写入kafka的数据不丢失,则需要保证ISR列表里至少得有一个Follower ,保持与Leader的数据同步。写入数据的时候,需要保证写入Leader 成功同时Follower同步此数据成功,如果不能满足这2个条件则为写入失败,让生成者尝试重复写入,直到满足这2个条件为止。这样写入成功的数据,即使Leader 宕机,Follower 中还是会有数据存在保证不丢失
  6. acks参数。首先这个 acks 参数,是在 Kafka Producer,也就是⽣产者客户端⾥设置的,用于写入数据时的配置。这个参数实际上有三 种常⻅的值可以设置,分别是:0、1 和all。第一种设置为0:意思就是Producer 在客户端,只要把消息发送 出去,不管那条数据有没有在哪怕Partition Leader 上落到磁盘,都不管他,直接就认为这 个消息发送成功了。第二种设置为1:只要 Partition Leader接收到消息⽽且写⼊本地磁盘 了,就认为成功了,不管他其他的 Follower 有没有同步过去这条消息,此配置为Kafka的默认配置。第三种设置为all:Partition Leader 接收到消息之后,还必须要求 ISR 列表⾥跟 Leader保持同步的那些 Follower 都要把消息同步过去,才能认为这条消息是写⼊成功了。acks=all就可以代表数据⼀定不会丢失了吗?当然不是,如果你的 Partition 只有⼀个副本,也就是⼀个 Leader,任何 Follower都没有,此时ISR ⾥就⼀个 Leader,他接收完消息后宕机,也会导致数据丢失。所以说这个 acks=all,必须跟 ISR列表⾥⾄少有 2 个以上的副本配合使⽤,起码是有⼀个Leader 和⼀个 Follower 才可以保证数据不丢失。

Kafka的网络通信性能

  1. 客户端与服务端的交互。Kafka 的分布式消息存储的机制,每个 Kafka 服务端叫做⼀个 Broker,负责管理⼀台机器上的数据。客户端在发送消息到 Kafka Broker 的时候,⽐如说限定了 “OrderTopic” 的订单数据拆分 为 3 个 “Partition”,那么 3 个“Partition” 分别放在⼀个 Kafka Broker 上,那么也就是要把所有的订单数据分发到三个 Kafka Broker 上去。此时会走一个默认的负载均衡的策略对订单消息均匀的投放到三个 Kafka Broker上
  2. 频繁⽹络通信带来的性能低下问题。如果一条消息对应一个网络请求发送到一个Broker 上,会导致生产者频繁和Broker进行通信导致性能低下。针对这个问题kafka 做的2个优化,就是实现了 batch 机制和request 机制。
  3. batch 机制:在客户端放⼀个内存缓冲区,每次你写⼀条订单先放到内存缓冲区⾥ 去,然后在内存缓冲区⾥,会把多个消息给打包起来成为⼀个batch,默认 kafka 规定的 batch 的⼤⼩是16kb,当多条消息凑满16kb大小会成为一个batch,然后通过⽹络通信发送到 Broker 上去。在打包消息形成 batch的时候,必须是发送到同⼀个 Topic 的同⼀个Partition 的消息,才会进⼊⼀个 batch。
  4. request 机制:多个 batch 打包成⼀个 request。可以把多个发往同⼀个 Broker 的 batch 打包成⼀个request, 然后⼀个 request 通过⼀次⽹络通信发送到 那个 Broker 上去。这样⼜进⼀步提升了⽹络通信 的效率和性能。

Kafka对JVM GC问题的设计优化

  1. 上面有聊到,为了提供网络通信性能,kafka会有内存缓存机制,消息会先写入内存缓存中,然后多条消息组成batch进行网络通信发送。对于已发送batch中的数据按传统思想,代码中避免任何变量去引用batch中的数据,然后等待JVM自动回收掉这些内存垃圾。
  2. 但是如果需要JVM频繁进行GC释放内存,GC不管是CMS还是G1,即使设置的停顿数据足够断,他也还是有个“Stop the World”的过程,这大大影响到其他项目的运行,所以如何避免JVM频繁进行GC回收内存,又能把batch内存释放掉呢
  3. Kafka客户端内部实现了一个非常优秀的机制:缓冲池的机制。每个batch底层对应一块内存空间,当batch发送后,数据不再需要,也就是说这个内存空间不再使用了,此时这个内存空间不要给JVM去回收,而是放入一个缓冲池里。这个缓冲池里存放了很多块内存空间,下次有新的batch,可以直接冲缓冲池里拿一块内存去用,这样内存可以循环往复使用有限的内存,而且不用JVM来回收释放,也避免了频繁GC导致的工作线程停顿
  4. 如果缓冲池⾥的内存资源都占满了,现在缓冲池⾥暂时没有内存块了,还需要写入数据,这个时候怎么办呢?阻塞写⼊操作,不停的等待,直到有内存块释放出来,再继续写⼊消息。

转载地址:http://qqtwb.baihongyu.com/

你可能感兴趣的文章
【LEETCODE】20-Valid Parentheses
查看>>
【LEETCODE】290-Word Pattern
查看>>
【LEETCODE】36-Valid Sudoku
查看>>
【LEETCODE】205-Isomorphic Strings
查看>>
【LEETCODE】204-Count Primes
查看>>
【LEETCODE】228-Summary Ranges
查看>>
【LEETCODE】27-Remove Element
查看>>
【LEETCODE】66-Plus One
查看>>
【LEETCODE】26-Remove Duplicates from Sorted Array
查看>>
【LEETCODE】118-Pascal's Triangle
查看>>
【LEETCODE】119-Pascal's Triangle II
查看>>
【LEETCODE】88-Merge Sorted Array
查看>>
【LEETCODE】19-Remove Nth Node From End of List
查看>>
【LEETCODE】125-Valid Palindrome
查看>>
【LEETCODE】28-Implement strStr()
查看>>
【LEETCODE】6-ZigZag Conversion
查看>>
【LEETCODE】8-String to Integer (atoi)
查看>>
【LEETCODE】14-Longest Common Prefix
查看>>
【LEETCODE】38-Count and Say
查看>>
【LEETCODE】278-First Bad Version
查看>>