消息系统分类
- Peer-to-Peer
- 一般基于Pull或者Polling接收消息
- 发送到队列中的消息被一个而且仅仅一个接收者所接收,即使有多个接收者在同一个队列中侦听同一消息
- 即支持异步“即发即弃”的消息传送方式,也支持同步请求/应答传送方式
- 发布/订阅
- 发布到一个主题的消息,可被多个订阅者所接收
- 发布/订阅即可基于Push消费数据,也可基于Pull或者Polling消费数据
- 解耦能力比P2P模型更强
消息系统适用场景
- 解耦 各位系统之间通过消息系统这个统一的接口交换数据,无须了解彼此的存在
- 冗余 部分消息系统具有消息持久化能力,可规避消息处理前丢失的风险
- 扩展 消息系统是统一的数据接口,各系统可独立扩展
- 峰值处理能力 消息系统可顶住峰值流量,业务系统可根据处理能力从消息系统中获取并处理对应量的请求
- 可恢复性 系统中部分组件失效并不会影响整个系统,它恢复后仍然可从消息系统中获取并处理数据
- 异步通信 在不需要立即处理请求的场景下,可以将请求放入消息系统,合适的时候再处理
常用消息系统对比
- RabbitMQ Erlang编写,支持多协议 AMQP,XMPP,SMTP,STOMP。支持负载均衡、数据持久化。同时支持Peer-to-Peer和发布/订阅模式
- Redis 基于Key-Value对的NoSQL数据库,同时支持MQ功能,可做轻量级队列服务使用。就入队操作而言,Redis对短消息(小于10KB)的性能比RabbitMQ好,长消息的性能比RabbitMQ差。
- ZeroMQ 轻量级,不需要单独的消息服务器或中间件,应用程序本身扮演该角色,Peer-to-Peer。它实质上是一个库,需要开发人员自己组合多种技术,使用复杂度高
- ActiveMQ JMS实现,Peer-to-Peer,支持持久化、XA事务【分布式事务】
- Kafka/Jafka 高性能跨语言的分布式发布/订阅消息系统,数据持久化,全分布式,同时支持在线和离线处理
- MetaQ/RocketMQ 纯Java实现,发布/订阅消息系统,支持本地事务和XA分布式事务
Kafka设计目标
- 高吞吐率 在廉价的商用机器上单机可支持每秒100万条消息的读写
- 消息持久化 所有消息均被持久化到磁盘,无消息丢失,支持消息重放
- 完全分布式 Producer,Broker,Consumer均支持水平扩展
- 同时适应在线流处理和离线批
Kafka架构
如何安装Kafka
- 在官网下载Kafka的压缩包
- 解压Kafka压缩包
- 启动Kafka自带的ZooKeeper
.bin/zookeeper-server-start.sh config/zookeeper.properties
- 【前台启动】
.bin/kafka-server-start.sh config/server.properties
- 【Kafka后台启动】
.bin/kafka-server-start.sh -daemon config/server.properties
- 查看端口是否被监听
- 这样就启动成功了
Kafka的简单使用
- 创建Topic,并指定一些参数【三个分区一个备份】
./bin/kafka-topics.sh --zookeeper localhost:2181 --create --topic test1 --partitions 3 --replication-factor 1
- Topic创建成功,并且有3个Partition
- 下图中的Isr:他会自动的去有副本的节点检查完整性,它要和主节点保持一致,副本会自动回复与主节点保持一致,如果有一天Leader的0号机挂了,没办法往0号读写消息,那么0号partition会重新寻找新的Leader,原则是副本优先Replicas,0号之后的第一个就是新的Leader。
- Kafka的Leader均衡【造成节点倾斜】:当所有的机器都挂了,重新启动这三台机器,那么会自动将新的Leader释放,把原先的Leader找回来,将读写操作的压力都均衡了
./bin/kafka-topics.sh --zookeeper localhost:2181 --describe --topic test1
- 创建好之后,可以通过运行以下命令,查看已创建的topic信息
./bin/kafka-topics.sh --list --zookeeper localhost:2181
- 启动Kafka的Consumer去订阅这个Topic的所有消息
./bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test1
- 发送消息【如果发送消息时,没有启动订阅服务,那么无法接受消息】
./bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test1
使用单独的ZooKeeper启动Kafka
- 启动ZooKeeper,并指定配置文件
./zkServer.sh start ../conf/zoo_sample.cfg
- 检测ZooKeeper的状态
./zkServer.sh stauts ../conf/zoo_sample.cfg
- 启动Kafka
./bin/kafka-server-start.sh config/server.properties
- 检测Kafka是否被监听
lsof -i:9092
- 创建一个topic
./bin/kafka-topics.sh --zookeeper localhost:2181 --create --topic test2 --partitions 3 --replication-factor 1
- 启动接收端
./bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test2
- 发送消息
./bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test2
- 删除topic
- 第一步:先删除 kafka-logs 目录下的想要删除的topic:rm -rf kafka-logs/topic名-*
- 第二步:delete删除想要删除的topic:./bin/kafka-topics.sh --zookeeper localhost:2181 --delete --topic topic名
- 第三步:查看topic:./bin/kafka-topics.sh --zookeeper localhost:2181 --list
- 第四步:想要立刻删除,还要删除ZooKeeper中的topic信息:rmr /brokers/topics/t0425
- 第五步:删除被删除标记所标记的topic:rmr /admin/delete_topics/t0425
- 第六步:再次查看就没有了
在ZooKeeper中去查找topic信息
- 注意:当没有使用【key,value】模式发布消息的时候,发送消息不采用hash机制,而是每隔十分钟就随机更改一次partition,改到那个partition,数据就存到那个分区,没有字符也算一条消息【空消息】