观察者模式,又叫发布-订阅模式
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
传统模式
生产者直接消息传递给指定的消费者
耦合性特别高,当生产者或者消费者发生变化,都需要重写业务逻辑
生产者消费者模式
通过一个容器来解决生产者和消费者的强度耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯。
数据传递过程
生产者消费模式,即N个线程进行生产,同时N个线程进行消费,两种角色通过内存缓冲区进行通信。
生产者负责向缓冲区里面添加数据单元
消费者负责从缓冲区里面取出数据单元
一般遵循先进先出的原则
解耦
假设生产者和消费者分别是两个类。如果让生产者直接调用消费者的某个方法,那么生产者对消费者就会产生依赖。
支持并发
生产者直接调用消费者的某个方法过程中函数调用是同步的
万一消费者处理数据很慢,生产者就会拜拜糟蹋大好时光
支持忙闲不均
缓冲区还有另一个好处,如果制造数据的速度时快时慢,缓冲区的好处就体现出来。
当数据制造快的时候,消费者来不及处理,未处理的数据可以暂时放在缓冲区中。
等生产者的制造速度慢下来,消费者再慢慢处理掉。
关联到业务对象
数据单元必须关联到某种业务对象
完整性
就是在传输过程中,要保证该数据单元的完整
独立性
就是各个数据单元之间没有互相依赖
某个数据单元传输失败不应该影响已经完成传输的单元;也不应该影响尚未传输的单元。
颗粒度
数据单元需要关联到某种业务对象。那么数据单元和业务对象应该处于的关系(一对一?一对多)
如果颗粒度过小会增加数据传输的次数
如果颗粒度过大会增加单个数据传输的时间,影响后期消费
一个消息系统负责将数据从一个应用传递到另一个应用,应用只需关注于数据,无需关注数据在两个或多个应用间是如何传递的。
在点对点消息系统中,消息持久化到一个队列中。此时,将有一个或多个消费者消费队列中的数据。但是一跳消息只能被消费一次。
当一个消费者消费了队列中的某条数据之后,该条数据则从消息队列中删除。
该模式即使有多个消费者同时消费数据,也能保证数据处理的顺序。
基于推送模型的消息系统,由消息代理记录消费状态。
消息代理将消息推送(push)到消费者后,标记这条消息为已经被消费,但是这种方式无法很好地保证消费的处理语义。
在发布-订阅消息系统中,消息被持久化到一个topic中。
消费者可以订阅一个或多个topic,消费者可以消费该topic中所有的数据,同一条数据可以被多个消费者消费,数据被消费后不会立马删除。
在发布-订阅消息系统中,消息的生产者称为发布者,消费者称为订阅者。
Kafka采取拉取模型(poll),由自己控制消费速度,以及消费的进度,消费者可以按照任意的偏移量进行消费。
Kafka是由Apache软件基金会开发的一个开源处理平台,由$cala和java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动作流数据。
以时间复杂度为o(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间的访问。
高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒100k条消息的传输。
支持KafkaServer间的消息分区,及分布式消费,同时保证每个partition内的消息顺序传输。
同时支持离线数据处理和实时数据处理。
支持在线水平扩展。
解耦
在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。消息系统在处理过程中间插入了一个隐含的、基数数据的接口层,两边的处理过程都要实现这一接口。这允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。
冗余
有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的“插入-获取-删除”范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。
扩展性
因为消息队列解耦了你的处理过程,所以增大消息入列和处理的频率是很容易的,只要另外增加处理过程即可,不需要改变代码、不需要调节参数。扩展就像大电力按钮一样简单。
灵活性&峰值处理能力
在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见:如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会突发的超负荷的请求而完全崩溃。
可恢复性
系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
顺序保证
在大多数使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。Kafka保证一个Partition内的消息的有序性。
缓冲
在任何重要的系统中,都会有需要不同的处理时间的元素,例如,加载一张图片比应用过滤器花费更少的时间。消息队列通过一个缓冲层来帮助任务最高效率的执行---写入队列的处理会尽可能的快速。该缓冲有助于控制和优化数据流经过系统的速度。
异步通信
很多时候,用户不想也不需要立即处理信息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它,想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
Kafka集群包含一个或多个服务器,服务器节点称为topic.
每条发布到kafka集群的消息都有一个类别,这个类别被称为Topic.
类似于数据库的表名或者index
物理上不同topic的消息分开存储
逻辑上一个topic的消息虽然保存于一个或多个broker上但用户只需指定信息的topic即可生产或消费数据而不必关心数据存于何处)
创建流程
删除流程
topic中的数据分割为一个或多个partition.
每个topic至少有一个partition,当生产者产生数据的时候,根据分配策略(Hash取模),选择分区,然后将消息追加到指定的分区的末尾(队列)
每条消息都会有一个自增的编号
标识顺序
用于标识消息的偏移量
每个partition中的数据使用多个segment文件存储。
Partition中的数量是有序的,不同partition间的数据丢失了数据的顺序。
如果topic有多个partition,消费数据时就不能保证数据的顺序。严格保证消息的消费顺序的场景下,需要将partition数目设为1。
Broker存储topic的数据。如果某topic有N个partition,集群有N个broker,那么每个broker存储该topic的一个partition.
如果某topic有N个partition,集群有(N+M)个broker,那么其中有N个broker存储topic的一个partition,剩下的M个broker不存储该topic的partition数据。
如果某topic有N个partition,集群中broker数目少于N个,那么一个broker存储该topic的一个或多个partition.在实际生产环境中,尽量避免这种情况的发生,这种情况容易导致KAFKA集群数据不均衡。
每个partition有多个副本,其中有且仅有一个作为Leader,leader是当前负责数据的读写的partition.
follower跟随Leader,所有写请求都通过Leader路由,数据变更会广播给所有Follower,Follower与Leader保持数据同步。
如果Leader失效,则从Follower中选举一个新的Leader.
当Follower挂掉,卡住或者同步太慢,leader会把这个follower从“in sync replicas”(ISR)列表中删除,重新创建一个Follower.
数据会存放到topic的partition中,但是有可能分区会损坏
我们需要对分区的数据进行备份(备份多少取决于你对数据的重视程度)
我们将分区的分为Leader(1)和Follower(N)
Leader负责写入和读取数据
Follower只负责备份
保证了数据的一致性
备份数设置为N,表示主+备=N
生产者即数据的发布者,该角色将消息发布到KAFKA的topic中。
Broker接收到生产者发送的消息后,broker将该消息追加到当前用于追加数据的segment文件中。
生产者发送的消息,存储到一个partition中,生产者也可以指定数据存储的partition。
消费者可以从broker中读取数据。消费者可以消费多个topic中的数据。
Kafka提供了两套consumerAPI:
每个Consumer属于一个特定的Consumer Group(可为每个Consumer指定group name,若不指定group name则属于默认的group)。
将多个消费者集中到一起去处理某一个Topic的数据,可以更快的提高数据的消费能力
整个消费者组共享一组偏移量(防止数据被重复读取),因为一个Topic有多个分区
可以唯一的标识一条消息
偏移量决定读取数据的位置,不会有线程安全的问题,消费者通过偏移量来决定下次读取的信息
消息被消费之后,并不被马上删除,这样多个业务就可以重复使用kafka的消息
我们某一个业务也可以通过修改偏移量达到重新读取消息的目的,偏移量由用户控制
消息最终还是会被删除的,默认生命周期为一周(7*24小时)
Kafka的存储文件逗死按照offset.kafka来命名,用offers做名字的好处是方便查找。
例如你想找位于2049的位置,只要找到2048.kafka的文件即可。当然the first offset就是00000000000.kafka
kafka通过zookeeper来存储集群的meta信息。
首先,我们需要下载zookeeper安装包,官网上无法下载的同学可以到我的网盘进行下载。
链接:https://pan.baidu.com/s/1-1hGBxFeywDl_8k0L53ysA
提取码:kskc
首先将下载的zookeeper传输到program文件夹里面,进行解压
cd /data/program
ll #会显示下载的安装包
tar -zxvf zookeeper-3.4.5.tar.gz #进行解压
cd /data/programe/zookeeper-3.4.5 #进入到解压后的文件夹
pwd #查询文件目录,进行复制
vi ~/.bash_profile #配置环境变量
export ZK_HOME=(zookeeper刚刚复制的文件目录)将这两行代码复制进去后保存
export PATH=$ZK_HOME/bin:$PATH
source ~/.bash_profile #就是保存将配置的环境启用
cd /data #进入data文件目录
mkdir tmp #创建一个为tmp的目录
mkdir zk #再创建一个为zk的目录,方便自己辨识
cd /data/tmp/zk #进入zk目录
pwd #复制该文件夹目录
cd /conf #进入coonf,你会看到zoo_sample.cfg zoo.cfg,
vi zoo.cfg #打开zoo.cfg,按i编辑,编辑号按esc退出,输入:x按enter保存退出
将上面复制的文件路劲与zoo.cfg里面的dataDir后的路劲替换,然后保存
cd /data/programe/zookeeper-3.4.5/bin #进入bin目录
ls #可以查看目录下的一些文件,可以看到zkServer.sh
./zkServer.sh start #启动zookeeper,你会看到会面有个Starting zookeeper...STARTED
./zkServer.sh status #你看到
./zkCli.sh #是与本地进行连接,没有报错表示连接成功。
./zkServer.sh stop #是要关闭zookeeper,但是暂时不要关,等你要关虚拟机的时候一定要启动这个命令,防止下一次再启动zookeeper话,报错了。
这样zookeeper就安装好了,下面我们来安装kafka。
首先,我们需要下载zookeeper安装包,官网上无法下载的同学可以到我的网盘进行下载。
链接:https://pan.baidu.com/s/1-1hGBxFeywDl_8k0L53ysA
提取码:kskc
和zookeeper相似,我们将下载好的kafka移动到program中,进行解压安装,详细步骤如下。
cd /data/program #进入到program目录
ls #你会看到kafka_2.11-0.9.0.0.tgzkafka的安装包
tar -zxvf kafka_2.11-0.9.0.0.tgz #进行解压
cd /data/software/kafka_2.11-0.9.0.0/bin #直接进入kafka文件下的bin目录
pwd #复制该文件路劲,配置环境变量
vi ~/.bsah_profile #进入该环境变量进行修改。
export KAFKA_HOME=(zookeeper刚刚复制的文件目录)将这两行代码复制进去后保存
export PATH=$KAFKA_HOME/bin:$PATH
source ~/.bash_profile #就是保存将配置的环境变量并启用
cd /data/tmp/ #进入该目录存储文件
mkdir kafka-logs #创建kafka的日志目录
pwd #复制该文件路径
cd /data/software/kafka_2.11-0.9.0.0 #直接进入kafka文件下
cd /config # 进入它的config目录下
ls #你会看到一个server.properties的配置文件
vi server.properties #打开这个配置文件进行修改
#找到host.name=192.168.200.188 #只要修改ip地址就行,你的地址替换我的ip地址就可以。
#找到log.dirs这一行,它是存储kafka的日志文件的,将log.dirs=后的路径替换刚刚复制的路径就行
#找到zookeeper.connect=xxxxxx,将localhost改为自己的ip地址,
例如zookeeper.connect=192.168.200.1888:2181,修改为这样即可。
最后按esc,输入:x进行保存退出
cd /data/software/kafka_2.11-0.9.0.0/ #进入kafka的目录
bin/kafka-server-start.sh config/server.properties #启动kafka
#创建一个tipic ,ip地址根据自己的ip修改,我们创建一个名为hello_topic的topic
kafka-topics.sh --create --zookeeper 192.168.200.188:2181 --replication-factor 1 --partitions 1 --topic hello_topic
#看到create hello_topic说明创建成功,下面我们来查看所创建的topic
bin/kafka-topics.sh --list --zookeeper 192.168.200.188:2181
#发送消息,我们需要双击一下我们的窗口,因为是单机,所以你多点几个窗口,如何操作在上一篇文章有说明
#生产消息,同样进入到kafka的文件夹
cd /data/software/kafka_2.11-0.9.0.0
#生产者生产日志信息
bin/kafka-console-producer.sh --broker-list 192.168.200.188:9092 --topic hello_topic
#在另一个窗口,同样进入kafka文件夹
#消费者消费信息
bin/kafka-console-consumer.sh --bootstrap-server 192.168.200.188:9092 --topic hello_topic
启动以后会和下列图片相等,说明你的安装配置完成了。
注意:bin/kafka-console-consumer.sh --bootstrap-server 192.168.200.188:9092 --topic hello_topic --from-beginning
加了--from-beginning,是从生产者从头开始输出,不加就是你从哪输入,就从哪输出。