MQ 学习 1

MQ 消息通讯


一:概念 

MQ(message queue):MQ是一种应用程序对应用程序的通信方法。应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接它们。 
消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。

二:AMQP协议介绍 

AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。 
AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。 
AMQP在消息提供者和客户端的行为进行了强制规定,使得不同卖商之间真正实现了互操作能力。

三:JMS协议介绍 

JMS(Java Messaging Service)是Java平台上有关面向消息中间件的技术规范,它便于消息系统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发。 
详情请移步至另一篇文章:http://blog.csdn.net/ruben95001/article/details/78363043

四:STOMP协议介绍 

STOMP,Streaming Text Orientated Message Protocol,是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。 
它提供了一个可互操作的连接格式,允许STOMP客户端与任意STOMP消息代理(Broker)进行交互,类似于OpenWire(一种二进制协议)。其中最流行的STOMP消息代理是Apache ActiveMQ。 
博主最初接触到的MQ就是ActiveMQ,当时的业务需求就是,要求用户通过WeChat的微信系统与我司研发的一款APP之间进行相互通信。起初博主当时打算是用第三方的服务,
例如环信,但是在熟读其文档后,发现与你用户体系有些不一致。便开始独立研发一套独立的通信系统,基于ActiveMQ。

五:MQ基本概念 

1:消息(Message) 

   消息是MQ中最小的概念,本质上就是一段数据,它能被一个或者多个应用程序所理解,是应用程序之间传递的信息载体。 

2:队列(Queue) 

   2.1:本地队列 

     本地队列按照功能可划分为初始化队列,传输队列,目标队列和死信队列。 
     2.1.1:初始化队列用作消息触发功能。 
     2.1.2:传输队列只是暂存待传的消息,条件许可的情况下,通过管道将消息传送到其他的队列管理器。 
     2.1.3:目标队列是消息的目的地,可以长期存放消息。 
     2.1.4:如果消息不能送达目标队列,也不能再路由出去,则被自动放入死信队列保存。 

   2.2:别名队列&远程队列 

	只是一个队列定义,用来指定远端队列管理器的队列。使用了远程队列,程序就不需要知道目标队列的位置。 

   2.3:模型队列 

	模型队列定义了一套本地队列的属性结合,一旦打开模型队列,队列管理器会按照这些属性动态地创建出一个本地队列。 

3:队列管理器(Queue Manager) 

   队列管理器是一个负责向应用程序提供消息服务的机构,如果把队列管理器比作数据库,那么队列就是其中一张表。 

4:通道(Channel) 

   通道是两个管理器之间的一种单向点对点的的通信连接,如果需要双向交流,可以建立一对通道。 

5:监听器(listner)

六:MQ产品的特性 

6.1:可靠性传输 

  对于应用来说,只要成功把数据提交给消息中间件,那么关于数据可靠传输的问题就由消息中间件来负责。 

6.2:不重复传输 

  不重复传播也就是断点续传的功能,特别适合网络不稳定的环境,节约网络资源。 

6.3:异步性传输 

  异步性传输是指,接受信息双方不必同时在线,具有脱机能力和安全性。 

6.4:消息驱动 

  接到消息后主动通知消息接收方。 

6.5:支持事务 

  目前MQ也广泛被一些企业用于对于分布式事务的同步。


七 常见的MQ对比 

    ActiveMQ 和 RabbitMq 以及Kafka 简单对比

	1) TPS/QPS(系统吞吐量)比较:

	Kafka最高,RabbitMq 次之, ActiveMq 最差。

	2) 吞吐量对比:

	kafka具有高的吞吐量,内部采用消息的批量处理,zero-copy机制,数据的存储和获取是本地磁盘顺序批量操作,具有O(1)的复杂度,消息处理的效率很高。
	rabbitMQ在吞吐量方面稍逊于kafka,他们的出发点不一样,rabbitMQ支持对消息的可靠的传递,支持事务,不支持批量的操作;基于存储的可靠性的要求存储可以采用内存或者硬盘。

	3) 在架构模型方面:

	RabbitMQ遵循AMQP协议,RabbitMQ的broker由Exchange,Binding,queue组成,其中exchange和binding组成了消息的路由键;客户端Producer通过连接channel和server进行通信,Consumer
	从queue获取消息进行消费(长连接,queue有消息会推送到consumer端,consumer循环从输入流读取数据)。rabbitMQ以broker为中心;有消息的确认机制。

	kafka遵从一般的MQ结构,producer,broker,consumer,以consumer为中心,消息的消费信息保存的客户端consumer上,consumer根据消费的点,从broker上批量pull数据;无消息确认机制。

	4) 在可用性方面,

	rabbitMQ支持miror的queue,主queue失效,miror queue接管。

	kafka的broker支持主备模式。

	activeMq也支持主备模式。

	5) 在集群负载均衡方面,

	kafka采用zookeeper对集群中的broker、consumer进行管理,可以注册topic到zookeeper上;

	通过zookeeper的协调机制,producer保存对应topic的broker信息,可以随机或者轮询发送到broker上;并且producer可以基于语义指定分片,消息发送到broker的某分片上。

	rabbitMQ的负载均衡需要单独的loadbalancer进行支持。

    综合对比:
	ActiveMQ: 历史悠久的开源项目,已经在很多产品中得到应用,实现了JMS1.1规范,可以和spring-jms轻松融合,实现了多种协议,不够轻巧(源代码比RocketMQ多),
	支持持久化到数据库,对队列数较多的情况支持不好。

	RabbitMq:
	它比kafka成熟,支持AMQP事务处理,在可靠性上,RabbitMq超过kafka,在性能方面超过ActiveMQ。

	Kafka:
	Kafka设计的初衷就是处理日志的,不支持AMQP事务处理,可以看做是一个日志系统,针对性很强,所以它并没有具备一个成熟MQ应该具备的特性
	Kafka的性能(吞吐量、tps)比RabbitMq要强,如果用来做大数据量的快速处理是比RabbitMq有优势的。


参考链接 https://blog.csdn.net/vtopqx/article/details/76382934

	https://blog.csdn.net/ruben95001/article/details/78366969


接下来主要已kafka 为主介绍,最近主要在看这方便的东西,其他几款,暂时没有做多学习和实践

Kafka 

入门

1、简介
    
    Kafka is a distributed,partitioned,replicated commit logservice。它提供了类似于JMS的特性,但是在设计实现上完全不同,此外它并不是JMS规范的实现。
    kafka对消息保存时根据Topic进行归类,发送消息者成为Producer,消息接受者成为Consumer,此外kafka集群有多个kafka实例组成,每个实例(server)成为broker。
    无论是kafka集群,还是producer和consumer都依赖于zookeeper来保证系统可用性集群保存一些meta信息。

2、主题和日志 (Topics/logs)

    一个Topic可以认为是一类消息,每个topic将被分成多个partition(区),每个partition在存储层面是append log文件。任何发布到此partition的消息都会被直接追加到log文件的尾部,
    每条消息在文件中的位置称为offset(偏移量),offset为一个long型数字,它是唯一标记一条消息。它唯一的标记一条消息。kafka并没有提供其他额外的索引机制来存储offset,
    因为在kafka中几乎不允许对消息进行“随机读写”。

    kafka和JMS(Java Message Service)实现(activeMQ)不同的是:即使消息被消费,消息仍然不会被立即删除.日志文件将会根据broker中的配置要求,
    保留一定的时间之后删除;比如log文件保留2天,那么两天后,文件会被清除,无论其中的消息是否被消费.kafka通过这种简单的手段,来释放磁盘空间,
    以及减少消息消费之后对文件内容改动的磁盘IO开支.
 
    对于consumer而言,它需要保存消费消息的offset,对于offset的保存和使用,有consumer来控制;当consumer正常消费消息时,offset将会"线性"的向前驱动,
    即消息将依次顺序被消费.事实上consumer可以使用任意顺序消费消息,它只需要将offset重置为任意值..(offset将会保存在zookeeper中,参见下文)
 
    kafka集群几乎不需要维护任何consumer和producer状态信息,这些信息有zookeeper保存;因此producer和consumer的客户端实现非常轻量级,它们可以随意离开,而不会对集群造成额外的影响.
 
    partitions的设计目的有多个.最根本原因是kafka基于文件存储.通过分区,可以将日志内容分散到多个server上,来避免文件尺寸达到单机磁盘的上限,每个partiton都会被当前server(kafka实例)保存;
    
    
    可以将一个topic切分多任意多个partitions,来消息保存/消费的效率.此外越多的partitions意味着可以容纳更多的consumer,有效提升并发消费的能力

3、 分布式

    一个Topic的多个partitions,被分布在kafka集群中的多个server上;每个server(kafka实例)负责partitions中消息的读写操作;此外kafka还可以配置partitions需要备份的个数(replicas),每个partition将会被备份到多台机器上,以提高可用性.
 
    基于replicated方案,那么就意味着需要对多个备份进行调度;每个partition都有一个server为"leader";leader负责所有的读写操作,如果leader失效,那么将会有其他follower来接管(成为新的leader);follower只是单调的和leader跟进,同步消息即可..由此可见作为leader的server承载了全部的请求压力,因此从集群的整体考虑,有多少个partitions就意味着有多少个"leader",kafka会将"leader"均衡的分散在每个实例上,来确保整体的性能稳定.
 
    Producers
    Producer将消息发布到指定的Topic中,同时Producer也能决定将此消息归属于哪个partition;比如基于"round-robin"方式或者通过其他的一些算法等.
 
    Consumers
    本质上kafka只支持Topic.每个consumer属于一个consumer group;反过来说,每个group中可以有多个consumer.发送到Topic的消息,只会被订阅此Topic的每个group中的一个consumer消费.
 
    如果所有的consumer都具有相同的group,这种情况和queue模式很像;消息将会在consumers之间负载均衡.
    如果所有的consumer都具有不同的group,那这就是"发布-订阅";消息将会广播给所有的消费者.
    在kafka中,一个partition中的消息只会被group中的一个consumer消费;每个group中consumer消息消费互相独立;我们可以认为一个group是一个"订阅"者,一个Topic中的每个partions,只会被一个"订阅者"中的一个consumer消费,不过一个consumer可以消费多个partitions中的消息.kafka只能保证一个partition中的消息被某个consumer消费时,消息是顺序的.事实上,从Topic角度来说,消息仍不是有序的.
 
    kafka的设计原理决定,对于一个topic,同一个group中不能有多于partitions个数的consumer同时消费,否则将意味着某些consumer将无法得到消息.
 
    备注
    1) 发送到partitions中的消息将会按照它接收的顺序追加到日志中
    2) 对于消费者而言,它们消费消息的顺序和日志中消息顺序一致.
    3) 如果Topic的"replicationfactor"为N,那么允许N-1个kafka实例失效.


4 名词解释

   producer:生产者。

   consumer:消费者。

   topic: 消息以topic为类别记录,Kafka将消息种子(Feed)分门别类,每一类的消息称之为一个主题(Topic)。

   broker:以集群的方式运行,可以由一个或多个服务组成,每个服务叫做一个broker;消费者可以订阅一个或多个主题(topic),并从Broker拉数据,从而消费这些已发布的消息。
	      每个消息(也叫作record记录,也被称为消息)是由一个key,一个value和时间戳构成。

 
5 应用场景

   1)、消息/Messaging   

       对于一些常规的消息系统,kafka是个不错的选择;partitons/replication和容错,可以使kafka具有良好的扩展性和性能优势.不过到目前为止,我们应该很清楚认识到,
       kafka并没有提供JMS中的"事务性""消息传输担保(消息确认机制)""消息分组"等企业级特性;kafka只能使用作为"常规"的消息系统,在一定程度上,
       尚未确保消息的发送与接收绝对可靠(比如,消息重发,消息发送丢失等)
	 
   2)、网站活性跟/Websit activity tracking
	   
       kafka可以作为"网站活性跟踪"的最佳工具;可以将网页/用户操作等信息发送到kafka中.并实时监控,或者离线统计分析等
	 

   3)、日志收集中心/Log Aggregation
	   
       kafka的特性决定它非常适合作为"日志收集中心";application可以将操作日志"批量""异步"的发送到kafka集群中,而不是保存在本地或者DB中;

       kafka可以批量提交消息/压缩消息等,这对producer端而言,几乎感觉不到性能的开支.此时consumer端可以使hadoop等其他系统化的存储和分析系统.


6 设计原理

	kafka的设计初衷是希望作为一个统一的信息收集平台,能够实时的收集反馈信息,并需要能够支撑较大的数据量,且具备良好的容错能力.
	 
	1、持久性
	kafka使用文件存储消息,这就直接决定kafka在性能上严重依赖文件系统的本身特性.且无论任何OS下,对文件系统本身的优化几乎没有可能.
	
	文件缓存/直接内存映射等是常用的手段.因为kafka是对日志文件进行append操作,因此磁盘检索的开支是较小的;同时为了减少磁盘写入的次数,
	broker会将消息暂时buffer起来,当消息的个数(或尺寸)达到一定阀值时,再flush到磁盘,这样减少了磁盘IO调用的次数.

	2、性能
	需要考虑的影响性能点很多,除磁盘IO之外,我们还需要考虑网络IO,这直接关系到kafka的吞吐量问题.kafka并没有提供太多高超的技巧;对于producer端,
	可以将消息buffer起来,当消息的条数达到一定阀值时,批量发送给broker;对于consumer端也是一样,批量fetch多条消息.不过消息量的大小可以通过配置文件来指定.
	对于kafka broker端,似乎有个sendfile系统调用可以潜在的提升网络IO的性能:将文件的数据映射到系统内存中,socket直接读取相应的内存区域即可,
	而无需进程再次copy和交换. 其实对于producer/consumer/broker三者而言,CPU的开支应该都不大,因此启用消息压缩机制是一个良好的策略;压缩需要消耗少量的CPU资源,
	不过对于kafka而言,网络IO更应该需要考虑.可以将任何在网络上传输的消息都经过压缩.kafka支持gzip/snappy等多种压缩方式.

	3、生产者
	负载均衡: producer将会和Topic下所有partition leader保持socket连接;消息由producer直接通过socket发送到broker,中间不会经过任何"路由层".事实上,
	消息被路由到哪个partition上,有producer客户端决定.比如可以采用"random""key-hash""轮询"等,如果一个topic中有多个partitions,那么在producer端实现"消息均衡分发"是必要的.

	其中partition leader的位置(host:port)注册在zookeeper中,producer作为zookeeper client,已经注册了watch用来监听partition leader的变更事件.

	异步发送:将多条消息暂且在客户端buffer起来,并将他们批量的发送到broker,小数据IO太多,会拖慢整体的网络延迟,批量延迟发送事实上提升了网络效率。
	不过这也有一定的隐患,比如说当producer失效时,那些尚未发送的消息将会丢失。


	4、消费者
	consumer端向broker发送"fetch"请求,并告知其获取消息的offset;此后consumer将会获得一定条数的消息;consumer端也可以重置offset来重新消费消息.

	在JMS实现中,Topic模型基于push方式,即broker将消息推送给consumer端.不过在kafka中,采用了pull方式,即consumer在和broker建立连接之后,主动去pull(或者说fetch)消息;
	这中模式有些优点,首先consumer端可以根据自己的消费能力适时的去fetch消息并处理,且可以控制消息消费的进度(offset);此外,消费者可以良好的控制消息消费的数量,batch fetch.

	其他JMS实现,消息消费的位置是有prodiver保留,以便避免重复发送消息或者将没有消费成功的消息重发等,同时还要控制消息的状态.这就要求JMS broker需要太多额外的工作.
	在kafka中,partition中的消息只有一个consumer在消费,且不存在消息状态的控制,也没有复杂的消息确认机制,可见kafka broker端是相当轻量级的.当消息被consumer接收之后,
	consumer可以在本地保存最后消息的offset,并间歇性的向zookeeper注册offset.由此可见,consumer客户端也很轻量级.


7 消息传送机制

	对于JMS实现,消息传输担保非常直接:有且只有一次(exactly once).在kafka中稍有不同:
	1) at most once: 最多一次,这个和JMS中"非持久化"消息类似.发送一次,无论成败,将不会重发.
	2) at least once: 消息至少发送一次,如果消息未能接受成功,可能会重发,直到接收成功.
	3) exactly once: 消息只会发送一次.
	at most once: 消费者fetch消息,然后保存offset,然后处理消息;当client保存offset之后,但是在消息处理过程中出现了异常,导致部分消息未能继续处理.
	
	那么此后"未处理"的消息将不能被fetch到,这就是"at most once".
	at least once: 消费者fetch消息,然后处理消息,然后保存offset.如果消息处理成功之后,但是在保存offset阶段zookeeper异常导致保存操作未能执行成功,
	
	这就导致接下来再次fetch时可能获得上次已经处理过的消息,这就是"at least once",原因offset没有及时的提交给zookeeper,zookeeper恢复正常还是之前offset状态.
	exactly once: kafka中并没有严格的去实现(基于2阶段提交,事务),我们认为这种策略在kafka中是没有必要的.

	通常情况下"at-least-once"是我们搜选.(相比at most once而言,重复接收数据总比丢失数据要好).

8、复制备份

	kafka将每个partition数据复制到多个server上,任何一个partition有一个leader和多个follower(可以没有);备份的个数可以通过broker配置文件来设定.

	leader处理所有的read-write请求,follower需要和leader保持同步.Follower和consumer一样,消费消息并保存在本地日志中;leader负责跟踪所有的follower状态,

	如果follower"落后"太多或者失效,leader将会把它从replicas同步列表中删除.当所有的follower都将一条消息保存成功,此消息才被认为是"committed",那么此时consumer才能消费它.

	即使只有一个replicas实例存活,仍然可以保证消息的正常发送和接收,只要zookeeper集群存活即可.(不同于其他分布式存储,比如hbase需要"多数派"存活才行)
	当leader失效时,需在followers中选取出新的leader,可能此时follower落后于leader,因此需要选择一个"up-to-date"的follower.选择follower时需要兼顾一个问题,

	就是新leaderserver上所已经承载的partition leader的个数,如果一个server上有过多的partition leader,意味着此server将承受着更多的IO压力.在选举新leader,需要考虑到"负载均衡".

9.日志

	如果一个topic的名称为"my_topic",它有2个partitions,那么日志将会保存在my_topic_0和my_topic_1两个目录中;日志文件中保存了一序列"log entries"(日志条目),
	每个log entry格式为"4个字节的数字N表示消息的长度" + "N个字节的消息内容";每个日志都有一个offset来唯一的标记一条消息,offset的值为8个字节的数字,表示此消息在此partition中所处的起始位置..每个partition在物理存储层面,有多个log file组成(称为segment).segmentfile的命名为"最小offset".kafka.例如"00000000000.kafka";其中"最小offset"表示此segment中起始消息的offset.

	其中每个partiton中所持有的segments列表信息会存储在zookeeper中.
	当segment文件尺寸达到一定阀值时(可以通过配置文件设定,默认1G),将会创建一个新的文件;当buffer中消息的条数达到阀值时将会触发日志信息flush到日志文件中,同时如果"距离最近一次flush的时间差"达到阀值时,也会触发flush到日志文件.如果broker失效,极有可能会丢失那些尚未flush到文件的消息.因为server意外实现,仍然会导致log文件格式的破坏(文件尾部),那么就要求当server启东是需要检测最后一个segment的文件结构是否合法并进行必要的修复.
	获取消息时,需要指定offset和最大chunk尺寸,offset用来表示消息的起始位置,chunk size用来表示最大获取消息的总长度(间接的表示消息的条数).根据offset,可以找到此消息所在segment文件,然后根据segment的最小offset取差值,得到它在file中的相对位置,直接读取输出即可.
	日志文件的删除策略非常简单:启动一个后台线程定期扫描log file列表,把保存时间超过阀值的文件直接删除(根据文件的创建时间).为了避免删除文件时仍然有read操作(consumer消费),采取copy-on-write方式.

10 分配
	kafka使用zookeeper来存储一些meta信息,并使用了zookeeper watch机制来发现meta信息的变更并作出相应的动作(比如consumer失效,触发负载均衡等)

	1) Broker node registry: 当一个kafkabroker启动后,首先会向zookeeper注册自己的节点信息(临时znode),同时当broker和zookeeper断开连接时,此znode也会被删除.
	格式: /broker/ids/[0...N]   -->host:port;其中[0..N]表示broker id,每个broker的配置文件中都需要指定一个数字类型的id(全局不可重复),znode的值为此broker的host:port信息.

	2) Broker Topic Registry: 当一个broker启动时,会向zookeeper注册自己持有的topic和partitions信息,仍然是一个临时znode.
	格式: /broker/topics/[topic]/[0...N]  其中[0..N]表示partition索引号.

	3) Consumer and Consumer group: 每个consumer客户端被创建时,会向zookeeper注册自己的信息;此作用主要是为了"负载均衡".
	一个group中的多个consumer可以交错的消费一个topic的所有partitions;简而言之,保证此topic的所有partitions都能被此group所消费,且消费时为了性能考虑,
	让partition相对均衡的分散到每个consumer上.

	4) Consumer id Registry: 每个consumer都有一个唯一的ID(host:uuid,可以通过配置文件指定,也可以由系统生成),此id用来标记消费者信息.
	格式:/consumers/[group_id]/ids/[consumer_id]
	仍然是一个临时的znode,此节点的值为{"topic_name":#streams...},即表示此consumer目前所消费的topic + partitions列表.

	5) Consumer offset Tracking: 用来跟踪每个consumer目前所消费的partition中最大的offset.
	格式:/consumers/[group_id]/offsets/[topic]/[broker_id-partition_id]-->offset_value
	此znode为持久节点,可以看出offset跟group_id有关,以表明当group中一个消费者失效,其他consumer可以继续消费.

	6) Partition Owner registry: 用来标记partition被哪个consumer消费.临时znode

	格式:/consumers/[group_id]/owners/[topic]/[broker_id-partition_id]-->consumer_node_id当consumer启动时,所触发的操作:
	A) 首先进行"Consumer id Registry";
	B) 然后在"Consumer id Registry"节点下注册一个watch用来监听当前group中其他consumer的"leave"和"join";只要此znode path下节点列表变更,
	都会触发此group下consumer的负载均衡.(比如一个consumer失效,那么其他consumer接管partitions).

	C) 在"Broker id registry"节点下,注册一个watch用来监听broker的存活情况;如果broker列表变更,将会触发所有的groups下的consumer重新balance.

	1) Producer端使用zookeeper用来"发现"broker列表,以及和Topic下每个partition leader建立socket连接并发送消息.
	2) Broker端使用zookeeper用来注册broker信息,已经监测partitionleader存活性.
	3) Consumer端使用zookeeper用来注册consumer信息,其中包括consumer消费的partition列表等,同时也用来发现broker列表,并和partition leader建立socket连接,并获取消息.


参考链接 https://www.cnblogs.com/likehua/p/3999538.html

	https://www.cnblogs.com/yangxiaoyi/p/7359236.html


zookeeper 简介

Zookeeper的功能以及工作原理

1.ZooKeeper是什么?

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。
最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户

2.ZooKeeper提供了什么?

	1)文件系统

	2)通知机制

3.Zookeeper文件系统

	每个子目录项如 NameService 都被称作为znode,和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。 

	有四种类型的znode: 

	1)、persistent -持久化目录节点 

	客户端与zookeeper断开连接后,该节点依旧存在 

	2)、persistent_sequential-持久化顺序编号目录节点 

	客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号 

	3)、ephemeral-临时目录节点 

	客户端与zookeeper断开连接后,该节点被删除 

	4)、ephemeral_sequential-临时顺序编号目录节点 

	客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号 

4.Zookeeper通知机制

	客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。

5.Zookeeper做了什么?

	1).命名服务   2).配置管理   3).集群管理   4).分布式锁  5).队列管理

6.Zookeeper命名服务

	在zookeeper的文件系统里创建一个目录,即有唯一的path。在我们使用tborg无法确定上游程序的部署机器时即可与下游程序约定好path,通过path即能互相探索发现。

7.Zookeeper的配置管理

	程序总是需要配置的,如果程序分散部署在多台机器上,要逐个改变配置就变得困难。现在把这些配置全部放到zookeeper上去,保存在 Zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中就好

8.Zookeeper集群管理

	所谓集群管理无在乎两点:是否有机器退出和加入、选举master。 

	对于第一点,所有机器约定在父目录GroupMembers下创建临时目录节点,然后监听父目录节点的子节点变化消息。一旦有机器挂掉,该机器与 zookeeper的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除,于是,所有人都知道:它上船了。

	新机器加入也是类似,所有机器收到通知:新兄弟目录加入,highcount又有了,对于第二点,我们稍微改变一下,所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为master就好。

9.Zookeeper分布式锁

	有了zookeeper的一致性文件系统,锁的问题变得容易。锁服务可以分为两类,一个是保持独占,另一个是控制时序。 

	对于第一类,我们将zookeeper上的一个znode看作是一把锁,通过createznode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。用完删除掉自己创建的distribute_lock 节点就释放出锁。 

	对于第二类, /distribute_lock 已经预先存在,所有客户端在它下面创建临时顺序编号目录节点,和选master一样,编号最小的获得锁,用完删除,依次方便。

10.Zookeeper队列管理

	两种类型的队列:

	1、同步队列,当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达。 

	2、队列按照 FIFO 方式进行入队和出队操作。 

	第一类,在约定目录下创建临时目录节点,监听节点数目是否是我们要求的数目。 

	第二类,和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。

11.分布式与数据复制 

	Zookeeper作为一个集群提供一致的数据服务,自然,它要在所有机器间做数据复制。数据复制的好处: 

	1)、容错:一个节点出错,不致于让整个系统停止工作,别的节点可以接管它的工作; 

	2)、提高系统的扩展能力 :把负载分布到多个节点上,或者增加节点来提高系统的负载能力; 

	3)、提高性能:让客户端本地访问就近的节点,提高用户访问速度。 

	从客户端读写访问的透明度来看,数据复制集群系统分下面两种: 

	1)、写主(WriteMaster) :对数据的修改提交给指定的节点。读无此限制,可以读取任何一个节点。这种情况下客户端需要对读与写进行区别,俗称读写分离; 

	2)、写任意(Write Any):对数据的修改可提交给任意的节点,跟读一样。这种情况下,客户端对集群节点的角色与变化透明。

	对zookeeper来说,它采用的方式是写任意。通过增加机器,它的读吞吐能力和响应能力扩展性非常好,而写,随着机器的增多吞吐能力肯定下降(这也是它建立observer的原因),而响应能力则取决于具体实现方式,是延迟复制保持最终一致性,还是立即复制快速响应。


12.Zookeeper角色描述

	leader : 负责投票的发起和决议,更新系统状态

	learner:
		follower:接受客户端请求并返回结果,参与投票
		observer:接受客户端链接,将写请求转发给leader ,不参与投票,只同步leader状态,目的:扩展系统,提高读取速度

	client: 发送请求


13.Zookeeper设计目的

	1).最终一致性:client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的性能。 

	2).可靠性:具有简单、健壮、良好的性能,如果消息被到一台服务器接受,那么它将被所有的服务器接受。 

	3).实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,
	如果需要最新数据,应该在读数据之前调用sync()接口。 

	4).等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每个client都能有效的等待。 

	5).原子性:更新只能成功或者失败,没有中间状态。 

	6).顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布;
	偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。 


14.Zookeeper工作原理

	Zookeeper 的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。
	当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。
	状态同步保证了leader和Server具有相同的系统状态。 

	为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,
	它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。

15.Zookeeper 下 Server工作状态

	每个Server在工作过程中有三种状态: 

	LOOKING:当前Server不知道leader是谁,正在搜寻
	LEADING:当前Server即为选举出来的leader
	FOLLOWING:leader已经选举出来,当前Server与之同步

16.Zookeeper选主流程(basic paxos)

	当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的Server都恢复到一个正确的状态。
	Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。

	1).选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server; 

	2).选举线程首先向所有Server发起一次询问(包括自己); 

	3).选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),
	并将这些信息存储到当次选举的投票记录表中; 

	4).收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server; 

	5).线程将当前zxid最大的Server设置为当前Server要推荐的Leader,如果此时获胜的Server获得n/2 + 1的Server票数,设置当前推荐的leader为获胜的Server,
	将根据获胜的Server相关信息设置自己的状态,否则,继续这个过程,直到leader被选举出来。 通过流程分析我们可以得出:要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1. 每个Server启动后都会重复以上流程。在恢复模式下,如果是刚从崩溃状态恢复的或者刚启动的server还会从磁盘快照中恢复数据和会话信息,zk会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。选主的具体流程图所示: 


17.Zookeeper选主流程(fast paxos)

	fast paxos流程是在选举过程中,某Server首先向所有Server提议自己要成为leader,当其它Server收到提议以后,解决epoch和 zxid的冲突,并接受对方的提议,
	然后向对方发送接受提议完成的消息,重复这个流程,最后一定能选举出Leader。


18.Zookeeper同步流程

	选完Leader以后,zk就进入状态同步过程。 

	1). Leader等待server连接; 

	2) .Follower连接leader,将最大的zxid发送给leader; 

	3) .Leader根据follower的zxid确定同步点; 

	4) .完成同步后通知follower 已经成为uptodate状态; 

	5) .Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。

19.Zookeeper工作流程-Leader

	1) .恢复数据; 

	2) .维持与Learner的心跳,接收Learner请求并判断Learner的请求消息类型; 

	3) .Learner的消息类型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根据不同的消息类型,进行不同的处理。 

	PING 消息是指Learner的心跳信息;

	REQUEST消息是Follower发送的提议信息,包括写请求及同步请求;

	ACK消息是 Follower的对提议的回复,超过半数的Follower通过,则commit该提议;

	REVALIDATE消息是用来延长SESSION有效时间。


20.Zookeeper工作流程-Follower

	Follower主要有四个功能: 

	1).向Leader发送请求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息); 

	2).接收Leader消息并进行处理; 

	3).接收Client的请求,如果为写请求,发送给Leader进行投票;

	4).返回Client结果。 


	Follower的消息循环处理如下几种来自Leader的消息: 

	1) .PING消息: 心跳消息; 

	2) .PROPOSAL消息:Leader发起的提案,要求Follower投票; 

	3) .COMMIT消息:服务器端最新一次提案的信息; 

	4) .UPTODATE消息:表明同步完成; 

	5) .REVALIDATE消息:根据Leader的REVALIDATE结果,关闭待revalidate的session还是允许其接受消息; 

	6) .SYNC消息:返回SYNC结果到客户端,这个消息最初由客户端发起,用来强制得到最新的更新。

参考链接 https://www.cnblogs.com/felixzh/p/5869212.html


kafka 安装

1 jdk1.8 安装


2 scala2.11.12 安装 (kafka 基于 scala 版本 所以,需要安装scala)

wget https://github.com/scala/scala/archive/v2.11.12.tar.gz


3 zookeeper 安装 

下载  zookeeper-3.4.10.tar.gz

tar -zxvf  zookeeper-3.4.10.tar.gz -C /usr/local

mv zookeeper-xxx zookeeper

cd zookeeper

将conf下的zoo_sample.cfg重命名为 zoo.cfg

主要修改一下日志位置,具体配置文件如下:

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/usr/local/zookeeper/data
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1


配置文件简单解析

1、tickTime:这个时间是作为Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。

2、dataDir:顾名思义就是Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。

3、dataLogDir:顾名思义就是Zookeeper 保存日志文件的目录

4、clientPort:这个端口就是客户端连接Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。


操作命令

1. 启动ZK服务: ./bin/zkServer.sh start

2. 查看ZK服务状态:./bin/zkServer.sh status

3. 停止ZK服务: ./bin/zkServer.sh stop

4. 重启ZK服务: ./bin/zkServer.sh restart

kafka 安装

wget  http://mirror.bit.edu.cn/apache/kafka/2.0.0/kafka_2.11-2.0.0.tgz


tar -zxvf kafka_2.11-2.0.0.tgz -C /usr/local

mv kafka_xxx kafka

cd kafka

vi config/server.properties

配置如下: 
     
       主要添加 advertised.host.name=127.0.0.1

		advertised.port=9092


# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# see kafka.server.KafkaConfig for additional details and defaults

############################# Server Basics #############################

# The id of the broker. This must be set to a unique integer for each broker.
broker.id=0
port=9092
############################# Socket Server Settings #############################

# The address the socket server listens on. It will get the value returned from
# java.net.InetAddress.getCanonicalHostName() if not configured.
#   FORMAT:
#     listeners = listener_name://host_name:port
#   EXAMPLE:
#     listeners = PLAINTEXT://your.host.name:9092
#listeners=PLAINTEXT://:9092
#host.name=127.0.0.1

# Hostname and port the broker will advertise to producers and consumers. If not set,
# it uses the value for "listeners" if configured.  Otherwise, it will use the value
# returned from java.net.InetAddress.getCanonicalHostName().
#advertised.listeners=PLAINTEXT://your.host.name:9092


advertised.host.name=127.0.0.1
advertised.port=9092


# Maps listener names to security protocols, the default is for them to be the same. See the config documentation for more details
#listener.security.protocol.map=PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL

# The number of threads that the server uses for receiving requests from the network and sending responses to the network
num.network.threads=3

# The number of threads that the server uses for processing requests, which may include disk I/O
num.io.threads=8

# The send buffer (SO_SNDBUF) used by the socket server
socket.send.buffer.bytes=102400

# The receive buffer (SO_RCVBUF) used by the socket server
socket.receive.buffer.bytes=102400

# The maximum size of a request that the socket server will accept (protection against OOM)
socket.request.max.bytes=104857600


############################# Log Basics #############################

# A comma separated list of directories under which to store log files
log.dirs=/usr/local/kafka/logs

# The default number of log partitions per topic. More partitions allow greater
# parallelism for consumption, but this will also result in more files across
# the brokers.
num.partitions=1

# The number of threads per data directory to be used for log recovery at startup and flushing at shutdown.
# This value is recommended to be increased for installations with data dirs located in RAID array.
num.recovery.threads.per.data.dir=1

############################# Internal Topic Settings  #############################
# The replication factor for the group metadata internal topics "__consumer_offsets" and "__transaction_state"
# For anything other than development testing, a value greater than 1 is recommended for to ensure availability such as 3.
offsets.topic.replication.factor=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1

############################# Log Flush Policy #############################

# Messages are immediately written to the filesystem but by default we only fsync() to sync
# the OS cache lazily. The following configurations control the flush of data to disk.
# There are a few important trade-offs here:
#    1. Durability: Unflushed data may be lost if you are not using replication.
#    2. Latency: Very large flush intervals may lead to latency spikes when the flush does occur as there will be a lot of data to flush.
#    3. Throughput: The flush is generally the most expensive operation, and a small flush interval may lead to excessive seeks.
# The settings below allow one to configure the flush policy to flush data after a period of time or
# every N messages (or both). This can be done globally and overridden on a per-topic basis.

# The number of messages to accept before forcing a flush of data to disk
#log.flush.interval.messages=10000

# The maximum amount of time a message can sit in a log before we force a flush
#log.flush.interval.ms=1000

############################# Log Retention Policy #############################

# The following configurations control the disposal of log segments. The policy can
# be set to delete segments after a period of time, or after a given size has accumulated.
# A segment will be deleted whenever *either* of these criteria are met. Deletion always happens
# from the end of the log.

# The minimum age of a log file to be eligible for deletion due to age
log.retention.hours=168

# A size-based retention policy for logs. Segments are pruned from the log unless the remaining
# segments drop below log.retention.bytes. Functions independently of log.retention.hours.
#log.retention.bytes=1073741824

# The maximum size of a log segment file. When this size is reached a new log segment will be created.
log.segment.bytes=1073741824

# The interval at which log segments are checked to see if they can be deleted according
# to the retention policies
log.retention.check.interval.ms=300000

############################# Zookeeper #############################

# Zookeeper connection string (see zookeeper docs for details).
# This is a comma separated host:port pairs, each corresponding to a zk
# server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002".
# You can also append an optional chroot string to the urls to specify the
# root directory for all kafka znodes.
zookeeper.connect=localhost:2181

# Timeout in ms for connecting to zookeeper
zookeeper.connection.timeout.ms=720000


############################# Group Coordinator Settings #############################

# The following configuration specifies the time, in milliseconds, that the GroupCoordinator will delay the initial consumer rebalance.
# The rebalance will be further delayed by the value of group.initial.rebalance.delay.ms as new members join the group, up to a maximum of max.poll.interval.ms.
# The default value for this is 3 seconds.
# We override this to 0 here as it makes for a better out-of-the-box experience for development and testing.
# However, in production environments the default value of 3 seconds is more suitable as this will help to avoid unnecessary, and potentially expensive, rebalances during application startup.
group.initial.rebalance.delay.ms=0


启动

./bin/kafka-server-start.sh config/server.properties

停止

./bin/kafka-server-stop.sh

创建Topic

./bin/kafka-topics.sh --create --zookeeper 127.0.0.1:2181 --replication-factor 1 --partitions 1 --topic test3

(含有副本)
./bin/kafka-topics.sh --create --zookeeper 127.0.0.1:2181 --replication-factor 2 --partitions 1 --topic shuaige

	--replication-factor 2   #复制两份

	--partitions 1 #创建1个分区

	--topic #主题为shuaige


列出所有Topic

./bin/kafka-topics.sh -list -zookeeper 127.0.0.1:2181

启动Producer并发送消息:

./bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test

./bin/kafka-console-producer.sh --broker-list 127.0.0.1:9092 --topic shuaige



启动Consumer并接收消息:

./bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning


下面介绍 php 使用 kafka 需要安装的环境(其他语言,这里暂时不提供)

1、安装php-rdkafka
# cd /usr/local/src/
# git clone https://github.com/arnaud-lb/php-rdkafka.git
# cd php-rdkafka
# /usr/local/php/bin/phpize
# ./configure --with-php-config=/usr/local/php/bin/php-config
# make all -j 5  // 最多允许5 个编译命令执行 加快速度
# make install

1、修改php.ini
# vi /etc/php.ini

##增加如下代码:##
extension=rdkafka.so

##查看是否安装成功:##
# /usr/local/php/bin/php  -m

php 安装扩展的方式 使用 phpize 


下面就是 php 程序具体调用 kafka ,未完待续......

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值