消息队列
简称为MQ,指的就是数据在一个容器中, 从容器一端传递到另一端的操作
消息队列,只能暂存数据,不能永久存储数据
作用:
1) 应用解耦合
2) 异步处理
3) 限流削峰
消息队列的协议:JMS (Java Message Server)
角色:
生产者(Producer)
消费者(Consumer)
消费模型:
#1.点对点消费模型
指的一条消息最终只能被一个消费者所消费
#2.发布订阅消费模型
指的一条消息最终被多个消费者所消费
Kafka
基本介绍
Apache Kafka是一款消息队列的中间件的产品
特点:
- 可靠性: 整个服务器不容易发生宕机的风险,以及数据也不容易丢失
- 可扩展性: Kafka集群可以很方便的进行扩容,不需要停机
- 耐用性: 存储在kakfa数据,可以持久化的保存到磁盘上
- 性能: Kafka具有高吞吐高并发,整个效率是非常快,可以保证零停机,零数据丢失
架构
Kafka:没有主从节点(任何节点都能成为主、从)
# 拓展
# 普通分布式架构
Yarn
ResourceManager
NodeManager
HDFS
NameNode
DataNode
Spark
Master
Worker
特点:
有主有从。主和从不管切换
# 公平分布式架构
Zookeeper:自身没有主从节点(任何节点都能成为主、从)QuorumPeerMain
Kafka:也没有主从节点(任何节点都能成为主、从)
ElasticSearch:项目课再说
特点:
进程名字都一样。没有主从,各个角色都能成为主从。
KafkaShell命令操作
# 1.创建Topic:
kafka-topics.sh --create --topic --bootstrap-server --partitions --replication-factor
# 2.查看Topic列表:
kafka-topics.sh --list --bootstrap-server
# 3.查看Topic的详细信息:
kafka-topics.sh --describe --topic --bootstrap-server
# 4.生产者发送消息:
kafka-console-producer.sh --topic --bootstrap-server
# 5.消费者接收消息:
kafka-console-consumer.sh --topic --from-beginning --bootstrap-server
# 6.查看消费者组信息:
kafka-consumer-groups.sh --describe --group --bootstrap-server
Kafka的Python代码
# 生产者
from kafka import KafkaProducer
producer = KafkaProducer(bootstrap_servers=['broker1:1234'])
# Asynchronous by default
future = producer.send('my-topic', b'raw_bytes')
producer.flush()
# 消费者
from kafka import KafkaConsumer
#1.创建消费者对象
# To consume latest messages and auto-commit offsets
consumer = KafkaConsumer('my-topic',
group_id='my-group',
bootstrap_servers=['localhost:9092'])
#2.读取数据
for message in consumer:
# message value and key are raw bytes -- decode if necessary!
# e.g., for unicode: `message.value.decode('utf-8')`
print ("%s:%d:%d: key=%s value=%s" % (message.topic, message.partition,
message.offset, message.key,
message.value))
# 将数据生产到 Kafka
from kafka import KafkaProducer
#1.创建Kafka的生产者对象
producer = KafkaProducer(bootstrap_servers=['node1:9092','node2:9092','node3:9092'])
#2.向Kafka集群发送数据(生产数据)
#topic:Kafka的topic,如果不存在,则会创建
#producer.send('test03',b'test topic03').get()
#producer.send('test03','test topic03'.encode("UTF-8")).get()
producer.send('test03','好好学习,勤做练习'.encode("UTF-8")).get()
# 消费Kafka中数据
from kafka import KafkaConsumer
#1.创建Kafka消费者对象
consumer = KafkaConsumer('test03',
group_id='my-group',
bootstrap_servers=['node1:9092','node2:9092','node3:9092'])
#2.消费数据
for message in consumer:
# message value and key are raw bytes -- decode if necessary!
# e.g., for unicode: `message.value.decode('utf-8')`
print(message.topic)
print(message.partition)
print(message.offset)
print(message.key)
print(message.value.decode("UTF-8"))
Kafka的分区与副本机制
# 分区
Kafka中topic会划分为多个分片, 这些不同的分片均匀的落在不同的节点上
作用:
- 提高效率
- 提高存储容量, 分布式存储
# 副本
为保证分片的数据, 每一个分片设置副本
作用:
- 提高数据的可靠性, 避免数据的丢失
- 一般来说, 副本设置为 1~3
Kafka的数据不丢失机制
# 生产者如何保证数据不丢失
生产者保证数据不丢失是基于消息确认机制(ack机制),Kafka提供了三种ACK确认方案:
ack: 0
当ACK确认方案设置为0, 生产者将数据生产到Kafka集群中对应topic上某一个分片上,
不接收分片上返回任何的确认信息, 此种机制有可能导致数据丢失
ack: 1
当ACK确认方案设置为1, 生产者将数据生产到Kafka集群中对应topic上某一个分片上,
生产者会等待这个分片上主副本接收到消息后, 才认为数据生产成功了
ack:-1(ALL)
当ACK确认方案设置为1, 生产者将数据生产到Kafka集群中对应topic上某一个分片上,
生产者会等待这个分片上所有的副本都接收到消息后, 才认为数据生产成功了
从效率角度来看: 0 > 1 > -1
从安全角度来看: -1 > 1 > 0
请问, 在实际生产中, 选择那种ack方案呢? 三种方案可能都会使用的
主要时候根据生产的数据以及生产效率来判断的, 数据越不重要, 频率越高,
对应ack安全级别越低, 反之亦然
相对来说, 设置为 1 概率最多的 (默认为 1)
如何设置呢?
producer = KafkaProducer(bootstrap_servers=['xxx:9092'],acks=-1)
Kafka为什么快
#1.Kafka是顺序读写磁盘。节省磁头寻址的时间,提升写入和读取的效率。
#2.零拷贝,zero-copy,数据不经过用户态,直接在内核态完成传输。
sendfile
#3.epoll调用(多路复用)。
同步调用(epoll)多路复用。select、poll调用相比epoll效率较低。
异步调度(Window,Linux)