为什么高吞吐?
•写数据
–1.页缓存技术
•kafka写出数据时先将数据写到操作系统的pageCache上,由操作系统自己决定什么时候将数据写到磁盘上
–2.磁盘顺序写
•磁盘顺序写的性能会比随机写快上几百倍
•读数据
–常规的IO读文件流程
•1.OS从硬盘读取数据到内核区的pageCache缓存
•2.用户进程将数据拷贝到用户区的内存
•3.用户进程再把数据写到Socket缓存,数据流入内核区的SocketBuffer上
•4.OS在把数据从SocketBuffer中copy到网卡缓存,最后发送给客户端消费者
•零拷贝技术
数据重复消费和丢失
•producer端导致数据丢失
–producer在发送数据到kafka时,是保存在broker节点的pageCache内存上的,然后定期flush到磁盘,如果期间忽然断电,会造成数据丢失
•增加flush的刷新频率减少数据丢失量,但是不能保证数据一定不丢失,官方也不建议
•log.flush.interval.messages 当缓存中有多少条数据时触发溢写
•log.flush.interval.ms 每隔多久触发溢写log.flush.interval.ms 每隔多久触发溢写
–producer的ack默认设置为1,只能保证leader上数据的完整性,当follower还未同步好leader上的数据,而leader就挂了,也会导致数据的丢失
•设置ack=all,但是这样的性能非常低
•consumer端导致数据丢失
–consumer端消费者每隔一段时间会将offset保存到zookeeper上,如果提交offset太快,而这条数据还没消费完成,机器宕机,则这条数据就丢失了
•关闭自动提交offset,改为手动提交,在每次数据处理完成之后再提交
•数据重复消费
–consumer端向zookeeper提交offset太慢,数据已经消费了n条,而offset还未提交的过程中发生宕机,则下次消费则会重复消费数据
•关闭自动提交,改为手动提交
kafka是怎么数据怎么持久化?
•topic的数据存储在磁盘回默认存储到/tmp/kafka-logs目录下,也可以自己设置,一个分区一个目录,一个目录下多个segment文件,分为。index和.log文件
–.index文件伪索引文件,命名从0开始
–.log是由上一个文件最大的offset偏移量开头
•数据文件存放具体消息数据
–kafka从磁盘查找数据,先根据offset偏移量对index文件名字扫描,通过2分法查找,定位offset所在的索引文件,通过索引文件去对应的log文件查找数据
flume 和 kafka什么区别?
Flume是一个日志收集器,而kafka是一个消息队列
kafka为什么要分多个partition
若是只有一个topic,是无法解决水平扩展的问题,用partition解决
一个partition对应多个segment,一个segment有(log文件,和index文件),若不引入segment,那么一个partition对应一个文件,不符合kafka对文件的顺序写优化设计方案
kafka和spark Streaming 的整合
recriver模式,采用了recriver接收器模式,一个线程一直接受数据放到executor,默认级别:memoryanddiskser2,自动使用zookeeper管理消费者偏移量,recriver模式底层读取kafka采用high level consumer Api实现,这个模式不关系偏移量只要数据,当Driver挂掉,丢失数据,可以开启wal机制,但是会有数据重复消费的风险
Direct模式:没有使用recriver接受器模式,每批次处理数据直接获取当前批次数据处理,没有使用zookeeper管理消费者偏移量,使用的是spark自己管理,默认是存储在内存中,设置checkpoint,保存在checkpoint一份,底层读取kafka使用simple Consumer API,可以手动维护消费者偏移量,direct模式并行度和读取的topic的partition对应,设置checkpoint管理消费者偏移量,若是逻辑改变,无法从checkpoint恢复偏移量,可以放到redis
kafka的key为null可以吗
当key=null时,kafka是先从缓存中取分区号,然后判断缓存的值是否为空,如果不为空,就将消息存到这个分区,否则重新计算要存储的分区,并将分区号缓存起来,供下次使用
怎么往kafka集群写数据
在flume的配置文件的sink 和kafka的生产结合
kafka特性
高吞吐(读:IO流程,零拷贝计算,写:页缓存,磁盘顺序写),低延迟:每秒几十万消息,最低就几秒
可扩展性:kafka支持热扩展
持久性,可靠性:消息被持久化到本次磁盘,并防止数据备份丢失
容错性:允许集群中节点故障
高并发:支持数千个客户端同时写
Kafka的日志保存时间
7天
Kakfa分区数
分区数并不是越多越好,一般分区数不要超过集群机器数量。分区数越多占用内存越大(ISR等),一个节点集中的分区也就越多,当它宕机的时候,对系统的影响也就越大。
分区数一般设置为:3-10个
多少个Topic
多少个日志类型就多少个Topic。也有对日志类型进行合并的。
Kafka的ISR副本同步队列
ISR(In-Sync Replicas),副本同步队列。ISR中包括Leader和Follower。如果Leader进程挂掉,会在ISR队列中选择一个服务作为新的Leader。有replica.lag.max.messages(延迟条数)和replica.lag.time.max.ms(延迟时间)两个参数决定一台服务是否可以加入ISR副本队列,在0.10版本移除了replica.lag.max.messages参数,防止服务频繁的进去队列。
任意一个维度超过阈值都会把Follower剔除出ISR,存入OSR(Outof-Sync Replicas)列表,新加入的Follower也会先存放在OSR中。
Kafka分区分配策略
在 Kafka内部存在两种默认的分区分配策略:Range和 RoundRobin。
•Range是默认策略。Range
–是对每个Topic而言的(即一个Topic一个Topic分),首先对同一个Topic里面的分区按照序号进行排序,并对消费者按照字母顺序进行排序。然后用Partitions分区的个数除以消费者线程的总数来决定每个消费者线程消费几个分区。如果除不尽,那么前面几个消费者线程将会多消费一个分区。
•RoundRobin:
–前提:同一个Consumer Group里面的所有消费者的num.streams(消费者消费线程数)必须相等;每个消费者订阅的主题必须相同。
–第一步:将所有主题分区组成TopicAndPartition列表,然后对TopicAndPartition列表按照hashCode进行排序,最后按照轮询的方式发给每一个消费线程。
Kafka挂掉
如果是Kafka消费能力不足,则可以考虑增加Topic的分区数,并且同时提升消费组的消费者数量,消费者数=分区数。(两者缺一不可)
如果是下游的数据处理不及时:提高每批次拉取的数量。批次拉取数据过少(拉取数据/处理时间
Kafka压测
Kafka官方自带压力测试脚本(kafka-consumer-perf-test.sh、kafka-producer-perf-test.sh)。Kafka压测时,可以查看到哪个地方出现了瓶颈(CPU,内存,网络IO)。一般都是网络IO达到瓶颈。