kafka也是一种消息队列:异步,解耦,削峰
生产消费
消息队列
分类
1、Pull to Pull - P2P - 点对点模式
市面上绝大部分的消息队列都是点对点模式或者支持点对点模式
点对点模式下,数据往往只能被消费一次
2、Publish/Subscribe - 发布订阅模式
市面上会有较少的队列使用发布订阅模式
发布者订阅模式下,数据往往可以被多次消费
作用
解耦:生产者和消费者之间不会再产生耦合,即生产者或者消费者产生变化,另一端不需要跟着变
数据可靠性:部分消息队列收到数据之后会将数据存储在本地磁盘上,从而保证一定程度上消息不会丢失
消峰限流:一定程度缓解服务器的并发压力
kafka概述
Kafka是LinkedIn(领英)开发后来贡献给了Apache的一套纯粹的发布订阅模式的(kafka不支持点对点)、分布式的实时流消息队列
Kafka的特征:
1、发布订阅消息流
2、允许存储消息流并且提供了容错机制
3、实时处理消息流
Kafka的应用场景:
1、能够在系统或者应用之间,构建可靠的、实时的用于获取数据流的管道
2、能够构建一个转化或者处理数据流的应用
Kafka会接收到的数据存储到本地磁盘(持久化)上,而且单节点的Kafka的吞吐量是60M/s~100M/s,Kafka底层采用"零拷贝"机制 (机械磁盘的速度80-120M/s)
内核态的数据每个操作系统上不一样。数据拷贝有寻址以及状态转换的问题。
数据从内核态传到内核态,叫做零拷贝。
Kafka的开发语言是Scala(不是java),基于Scala的特性,Kafka具有很好的安全性和扩展性 - 在Kafka中可以动态添加节点
Kafka默认不会清理日志(把数据存储在磁盘上),如果需要自动清理,那么需要在server.properties中将log.cleaner.enable的值设置为true
基于时间,基于分区文件大小
log.retension.hours=168 (7天清理一次)
log.segment.bytes=107374824 (达到这个大小会产生新的文件)
offset机制是为了防止数据被重复处理;索引机制是为了快速定位数据
offset机制
记录每个消费者组处理到topic里面的数据的偏移量。保证每一个消费者从kafka消费的时候不会消费重复数据。
每个组处理数据的速度不一样,有快有慢。不记录的话就不知道哪个消费者消费到哪里了。记录一下,每一个消费者上一次读到哪了。
这个信息由消息队列维护。因为消息队列自己会清理日志,清理了就自己调整。
索引机制
一个消费者上次消费的offset是100,现在要从101条数据开始读。怎么知道101条数据在哪里,在log文件里面从哪里开始算是101条数据呢?
.index文件,记录偏移量和起始字节位置
不是每条数据都建立索引,而是挑选了部分数据建立索引——稀疏索引。101条数据大于100,就从100的起始字节位置开始读。
数据越来愈多,log文件会越来越大。当log文件达到1G的时候会产生一个新的log文件以及一个新的index文件,一一对应的。 log+index合起来称之为segment.
对索引的查找采用二分查找。为了快。
关键词:稀疏索引+二分查找。
索引文件被映射到内存中,查找还是很快的。
kafka安装
开启三台云主机
1. 启动Zookeeper
cd /home/software/zookeeper-3.4.8/bin
sh zkServer.sh start
2. 在第一个节点上进入software目录下,下载Kafka的安装包
cd /home/software/
wget http://bj-yzjd.ufile.cn-north-02.ucloud.cn/kafka_2.11-1.0.0.tgz
3. 解压安装包
tar -xvf kafka_2.11-1.0.0.tgz
4. 进入config目录下
cd kafka_2.11-1.0.0/config
5. 编辑server.properties
vim server.properties
修改
# 要求编号唯一
broker.id=0 # 每一个Broker需要分配一个唯一的编号
log.dirs=/home/software/kafka_2.11-1.0.0/kafka-logs # kafka会把数据存到本地磁盘下,就是这个目录
zookeeper.connect=hadoop01:2181,hadoop02:2181,hadoop03:2181
6. 进入bin目录启动Kafka
cd ../bin
sh kafka-server-start.sh ../config/server.properties
停止kafka,将第一个节点上的kafka拷贝到2,3节点
删除2,3节点上面的kafka-logs目录
修改其中的broker_id
启动1,2节点上面的kafka
基本概念
1、broker:经纪人,代理
在Kafka集群中,每一个Kafka节点就是一个Broker
每一个Broker需要分配一个唯一的编号
2、topic:话题/主题
作用:对数据进行分类
在Kafka中,每一条数据必须指定一个topic,即每一条数据都是对应一个分类 (每一条数据必须有一个分类)
一个topic至少要包含1个partition,也可以包含多个partition
3、partition:分区
每一个partition在磁盘上都会对应一个目录,一个topic有几个partition,在磁盘上就对应了几个目录
如果存在多个分区,多个分区会自动平均分配到每一个Kafka节点上,这样做的目的是为了是数据的负载均衡,分散压力
4、replication:副本
作用是保证的数据的高可用
指定几个副本,就会将当前的topic备份几个(备份数乘以分区数,然后轮流着放,不会把相同的分区放在一起,尽量均匀)
副本数量不能超过节点数量
5、producer:生产者。向Kafka放入数据
6、consumer:消费者
从Kafka获取数据
在Kafka中数据可以被获取多次
7、leader和follower:
多个副本之间会进行选举(???谁来选,controller,也和zk相关),自动选出一个leader副本和多个follower副本(主从备份,数据备份的系统里面总是有一个主其他的从;往主副本里面写,然后主副本去同步follower副本)
leader和follower说的是副本关系,和当前Kafka节点没有关系 - 一个kafka节点中既可能存在leader副本也可能存在follower副本
producer和consumer在和Kafka进行交互(读和写都是的)的时候,只和leader副本进行交互
当leader副本的数据发生变化的时候,同步给follower副本
8、controller:控制器
作用:在副本之中选举出一个leader副本
当Kafka集群启动的时候,Zookeeper会在Kakfa集群的某一个节点上来启动一个controller进程 (我觉得应该是zkfc)controller会自动在Zookeeper上注册一个临时节点,当controller进程意外结束的时候,Zookeeper上的这个节点也会随之消失,Zookeeper就会在Kafka的其他存活节点上来重新启动一个controller
Zookeeper会自动给controller分配一个递增的id(epoch id)
登录zk上,可以看到一个controller节点。get /controller
版本是1,controller节点在brokerid=1的节点上。
9、Consumer group - 消费者组:
可以将一个或者多个消费者放到一个消费者组中(多个消费者放到一起,一个组的consumer一起消费,组内的成员不会重复消费)
如果不指定,则默认一个消费者对应了一个消费者组
不同的消费者组可以共享相同的数据,但是数据只能被这个消费者组中的一个消费者处理 - 组间共享,组内竞争
基本命令
sh kafka-topics.sh --create --zookeeper hadoop01:2181 --replication-factor 1 --partitions 1 --topic news
创建一个主题叫news,创建主题需要连接zk,提供一个zk地址即可。
kafka-logs多一个目录叫做news-0;
–partitions 2 会有两个目录 music-0,music-1
sh kafka-topics.sh --list --zookeeper hadoop01:2181
查看现在已经有的topic,需要从zk上获取数据,zk中间人,管理数据的
sh kafka-topics.sh --delete --zookeeper hadoop01:2181 --topic video
删除topic。在删除的时候,默认情况下不是立即删除,只是标记删除,等待30~60s之后才会删除
sh kafka-console-producer.sh --broker-list hadoop01:9092 --topic log
启动生产者,控制台生产消息。连接到kafka的一个broker生产消息
sh kafka-console-consumer.sh --zookeeper hadoop01:2181 --topic log
启动消费者,消费在连接到zk获取和主题相关的消息
消息流
producer产生数据之后,将数据发送给leader副本
当leader副本收到数据之后,会将数据写到本地的日志中(write ahead log),然后等待.
follower副本定时的给leader副本发送信号(拉取数据),询问是否有新的信息需要同步
当leader副本收到信号之后,会将新的数据发送给follower副本要求同步
follower副本在收到信息之后,会将信息记录到本地日志中(follower也是先WAL),如果记录成功,则会给leader副本返回一个ack
当leader副本收到ACK之后,会记录这个副本所对应的brokerid(ISR)【记录一下谁找过我要了,要到哪了,有哪些节点持有我的数据副本,也会记录自己。会把这个ISR发送到zookeeper身上,如果leader挂了,会从剩下的几个副本里面选择一个作为controller,】,同时给producer返回一个ack。
ISR的作用:当leader副本所在的节点宕机的时候,可以考虑从ISR队列中随机选择一个副本成为新的leader
kafka HA
战斗到最后一个
kafka API
实际开发中写得不多
消息系统语义
至少一次(消费)(悲观思想)
生产者往MQ塞数据,但是生产者不确定是否塞成功,可能由于网络问题塞失败。
所以生产者需要消息队列返回ACK;ack丢失的时候可能存在重复发送的情况
至多一次
不管有没有收到,生产者只发一次(乐观思想)
精确一次
加入幂等,不管发多少次,MQ接受一次和接受多次的效果是相同的。不重复不丢失。
表单的重复提交上。登录,注册,支付,购物。重复点击时【网络卡】保证结果不会出错。数据的最终一致性也可以用这个——支付和增加积分。
后台通过jssessionid来做,接到多次,只处理一次,抛弃其他的。
预习笔记中,可以跟着代码执行一遍。
kafka参数配置
参考预习笔记
CAP理论
CAP:
Consistency:一致性 - 更新数据以后能够获取到集群中的最新数据 ,集群中的数据是一致的,都可以达到最新的数据。
Availability:可用性 - 只要服务器存活,在接收请求之后能够立即返回有效结果,强调时效性
Partition tolerance:分区容忍性(由于网络分区了) - 在集群中,不会因为一个或者几个节点宕机就导致整个集群不服务
经过数学证明,CAP三大理论无法同时满足,最多只能满足其中的2个
在分布式中,优先考虑满足P【集群越大故障率越高,总不可能几个节点挂了集群就不行了吧】,所以导致分布式集群基本都是CP或者AP系统
分区容忍,可以连接任何一个节点读取数据。如果要保证拿到最新数据,那就需要数据同步,这个是需要消耗时间的,就无法满足A了——时效性无法满足。如果是立即返回的话,又无法保证返回的是最新数据了。
CA系统:不存在与分布式系统中,只能是单台节点时。但是又没有分区容忍了,一个节点挂了,就不能提供服务了。数据最新,而且可以立马返回。
zookeeper:原子广播——CP系统
hadoop:副本,一致性——也是CP系统
一致性(C)的分类: 下面的几种都可以返回更新后的数据
强一致性:当一个节点的数据产生变化的时候,其他节点能够立即感知到这个变化
弱一致性:当一个节点的数据产生变化的时候,其他节点能够感知到部分变化或者没有感知
最终一致性:不关心中间变化过程,但是要求最后各个节点的数据是一样的
数据一致性的实现方式:
- Master/Slave:利用主节点控制从节点的一致性,例如主从复制(最简单的一种结构)
- PAXOS算法及其变种:在这种集群中不区分主从,例如Zookeeper(zookeeper有leader和follower,但是zk是不区分主从的,在搭建集群的时候,是无法确定那个节点是主哪个是从的,主从上面的配置是一模一样的,主从复制里面,主从上面的配置是不一样的,配置文件是不一样的)
- WNR:W表示写入节点个数,R表示读取节点个数,N表示总节点个数,WNR要求W+R>N,例如Cassandra
10个人,4个人有复习资料。获取数据时为了保证能够拿到复习资料,需要询问7个人,N=10个,数据写入成功到4个,要保证拿到最新数据就需要读取7个节点。例如Cassandra 数据库,采用的就是WNR策略保证数据一致性。