消息中间件kafka学习总结
Kafka简介
Kafka是一种分布式的,基于发布/订阅的消息系统。
消息中间件优点
1.解耦:在开始开发时,可以将产出的不一定明确的数据放入消息系统,这样可以保证最大程度的解耦和性,如果事soa或者微服务架构的话,其他模块想要有交集的时候直接去访问消息系统就可以,两个系统之间会保证独立,不回产生交集。
2.缓冲:数据可以不必直接存入数据库,这样减少了数据库的压力,小程度的减少了成本。
3.异步:生产者可以直接将数据放入消息系统不必立即处理,等待其他消费者来接收和处理数据。
kafka优点
1同时为发布和订阅提供高吞吐量。
2可进行持久化操作。将消息持久化到磁盘,通过将数据持久化到硬盘以及replication防止数据丢失。
3分布式系统,易于向外扩展。所有的producer、broker和consumer都会有多个,均为分布式的。无需停机即可扩展机器。
4.容错性。Kafka每个Partition数据会复制到几台服务器,当某个Broker失效时,Zookeeper将通知生产者和消费者从而使用其他的Broker。
kafka与其他中间件比较
1.kafka采用pull的方式获取数据,和传统的MQ不同,消费者需要自己保留一个offset,从kafka 获取消息时,只拉去当前offset 以后的消息。将offset 保存到zookeeper 上。每个消费者可以选择一个id,同样id 的消费者对于同一条消息只会收到一次。
2.可进行持久化操作,数据持久化到磁盘,通过将数据持久化到硬盘以及replication防止数据丢失。并且数据是多副本的,防止数据丢失。
3.kafka采取消费分区,且消费者有组的概念,同组中不同的消费者,消费不同的分区数据,同一个分区,数据是有序的。
Kafka数据传输的事务特点
1.at most once:最多一次,这个和JMS中"非持久化"消息类似,发送一次,无论成败,将不会重发。消费者fetch消息,然后保存offset,然后处理消息;当client保存offset之后,但是在消息处理过程中出现了异常,导致部分消息未能继续处理。那么此后"未处理"的消息将不能被fetch到,这就是"at most once"。
2.at least once:消息至少发送一次,如果消息未能接受成功,可能会重发,直到接收成功。消费者fetch消息,然后处理消息,然后保存offset。如果消息处理成功之后,但是在保存offset阶段zookeeper异常导致保存操作未能执行成功,这就导致接下来再次fetch时可能获得上次已经处理过的消息,这就是"at least once",原因offset没有及时的提交给zookeeper,zookeeper恢复正常还是之前offset状态。
3.exactly once:消息只会发送一次。kafka中并没有严格的去实现(基于2阶段提交),我们认为这种策略在kafka中是没有必要的。
通常情况下"at-least-once"是我们首选。
4.直接使用Linux 文件系统的cache,来高效缓存数据
kafka消费者采用pull方式获取数据的好处。
1.pull数据可把压力全部转移到消费者身上,消费者多个,这样kafka可以更好地实现高吞吐。
2.pull方式消费者可以根据自己的承载能力拉取数据,如果push方式,消费者的服务器无法承受如此大的数据量很有可能崩溃
Kafak顺序写入与数据读取
生产者(producer)是负责向Kafka提交数据的,Kafka会把收到的消息都写入到硬盘中,它绝对不会丢失数据。为了优化写入速度Kafak采用了两个技术,顺序写入和MMFile。
顺序写入
因为硬盘是机械结构,每次读写都会寻址,写入,其中寻址是一个“机械动作”,它是最耗时的。所以硬盘最“讨厌”随机I/O,最喜欢顺序I/O。为了提高读写硬盘的速度,Kafka就是使用顺序I/O。
每条消息都被append到该Partition中,属于顺序写磁盘,因此效率非常高
即便是顺序写入硬盘,硬盘的访问速度还是不可能追上内存。所以Kafka的数据并不是实时的写入硬盘,它充分利用了现代操作系统分页存储来利用内存提高I/O效率。
在Linux Kernal 2.2之后出现了一种叫做“零拷贝(zero-copy)”系统调用机制,就是跳过“用户缓冲区”的拷贝,建立一个磁盘空间和内存空间的直接映射,数据不再复制到“用户态缓冲区”系统上下文切换减少2次,可以提升一倍性能。
知识点:
数据分配到那个分区上是有生产者决定的,通过hash(key)%num(分区),来决定数据存到那个分区上面。
acks:此配置实际上代表了数据备份的可用性。
acks=0: 设置为0表示producer不需要等待任何确认收到的信息。副本将立即加到socket buffer并认为已经发送。没有任何保障可以保证此种情况下server已经成功接收数据,同时重试配置不会发生作用
acks=1: 这意味着至少要等待leader已经成功将数据写入本地log,但是并没有等待所有follower是否成功写入。这种情况下,如果follower没有成功备份数据,而此时leader又挂掉,则消息会丢失。
acks=all: 这意味着leader需要等待所有备份都成功写入日志,这种策略会保证只要有一个备份存活就不会丢失数据。这是最强的保证。
面试总结:http://www.jinciwei.cn/b832787.html
丢失原因:kafka挂掉(通过上面的回调函数进行弥补)
1 生产方向kafka发送消息,kafka挂掉,可以通过上面callback回调的方式进行弥补(可以写入hdfs)
设置数据发送失败重试 retries=3 发送方
通过确认机制:rack设置 0 发送就完成这条消息 1 等待leader返回接收消息 all 等待leader和副本 返回接收消息完毕(kafka内部)
手动提交:如果自动提交出现问题,offset发生改变,则数据出现丢失,则需要自己手动提交(消费)
重复:生产数据的时候出现重复 key放到redis 来了数据看是否有重复数据,无提交offset 如果放入hbase rowkey相同 则无问题
kafka的一致性重要机制之ISR
每个partition有一个leader和多个follower follower就类似consumer pull leader的数据 ,follower并不向外提供服务,它只是leader的一个备份,leader挂掉 做数据的备份
pull策略
同步:等待所有的follower抓取完成再进行提交 ,一致性好 可用性不高
异步:只要leader 拿到数据立即提交,等待follower慢慢去复制,很有可能复制失败,可用性好,一致性不高
ISR机制:
leader会维护一个ISR信息表,每个follower也会维护一张ISR表与之对应,如果两个表相差太多,或者长时间无复制,follower则会发起复制请求,当所有follower都发送ack时候,leader才会提交
rerplica.lag.time.max.ms=10000 10秒
rerplica.lag.max.messages=4000 相差4000条
提交:是指leader告诉客户端,这条数据写成功了。kafka尽量保证commit后立即leader挂掉,其他flower都有该条数据。
kafka堆积总结
1.kafka集群重启,2.还有就是版本不一致,造成每次推给消费的都是很大量的消息,消费再单位时间内处理不完,进行回滚,造成堆积
个人理解:可以增多partition和消费端的个数 增大并发度,对代码的修改 改为多线程
如果是kafka内部的问题 则需要进一步进行解决(可能是重复消费问题)
zk作用:
1.broker再zk中注册,broker会上报zk它的brokerid,broker会向zk定时发送心跳,如果broker挂掉,zk会删除该节点,它的partition会发到其他的机器,实现负载均衡
2.topic再zk注册:
每个broker会有多个topic,所以topic会向zk注册,他们的关系也是zk在维护
3.消费者再zk中注册:
3.1 zk会创建相关节点来保存相关信息,路径为:/consumers/{group_id}/ [ids,owners,offset]
ids:记录该消费分组有几个正在消费的消费者,Owmners:记录该消费分组消费的topic信息,Offset:记录topic每个分区中的每个offset
3.2 监听消费者分组中消费者的变化 ,监听/consumers/{group_id}/ids的子节点的变化,一旦发现消费者新增或者减少及时调整消费者的负载均衡。