用一句话来介绍一下kafka:kafka是一个高吞吐、低延迟的分布式流平台,本质是一个消息队列。
简单提一下kafka的历史,它最初是由linkedin开发用于各种日志数据传输,后来开源出来并交由Apache孵化。
先讲一下关于消息队列的一些内容以及为什么要用消息队列。
消息队列可以想象成一个大的漏斗,上面放,下面取。有什么好处呢?拿数据抓取到解析到清洗到入库这个过程举例说明消息队列的优点,大概可以分这几个方面:
1. 解耦。我为了业务解耦以及便于回溯问题把各过程拆离,那么中间的数据流转交给消息队列来做再合适不过了:爬虫抓完数据放到漏斗A里,解析的程序从漏斗A取数据,然后解析结束后放到漏斗B,清洗的程序从漏斗B取数据,清洗结束后放到漏斗C,入库的程序从漏斗C取数据,直接存数据库。
2. 扩展性。因为消息队列即漏斗的存在,我很轻松可以做分布式部署:100台爬虫服务器都向漏斗A写数据,3台解析分别取数据。最大程度发挥服务器性能。
3. 缓冲。假设入数据库过程比较慢,漏斗里面也能保存着数据不至于丢失。
4. 容灾。某部分挂掉不会影响其他部分,这其实也是强调解耦的好处。
5. 异步。针对web服务而言,可以把耗时长的任务写到消息队列,异步去处理。就像Celery就是做这个的例子。
6. 顺序性。队列的意思就是保证先进先出,在有严格顺序要求的场景用消息队列很合适。
7. 送达保证。在一定条件下,消息队列可以提供送达保证,也就是说保证这条消息被消费者消费掉了。
传统的消息队列里面 rabbitMQ 用得很广,它的路由、多协议、优先级队列等优点使它可以用于很多场景。kafka 强在高吞吐、低延迟上(得益于交于zookeeper异步维护offset)。
使用场景的对比:如果是传统的商城下单场景,用rabbitMQ就很合适。而如果是每天上亿URL的抓取任务调度,rabbitMQ就不如kafka做的好了。
再来讲一下kafka的架构模型。
1. Broker:指kafka集群中的一个或多个服务器
2. Topic:可以理解为不同的队列
3. Partition:这个是物理概念,一个Topic的数据实际会存在不同的Partition上。
4. Producer:生产者,写入消息到kafka的
5. Consumer:消费者,从kafka中读取消息的角色
6. Consumer Group:消费者组,下文详细讲。
kafka是基于消费者的拉模式做的。也就是说,消费者可以自己控制从kafka获取消息的速度。如果跟推模式做对比的话,推模式更及时,但是不顾及消费者的能力。拉模式可以充分发挥消费者性能,但也会造成一定的消费延迟。
kafka 有消费组概念,什么意思呢,就是说属于同一组的消费者,每条消息只能消费一次。在分布式抓取架构里面,调度中心分配1亿条URL抓取任务到kafka,然后几十台甚至上百台抓取服务器可以在一个消费组里面,这样就保证了URL不会被重复抓取,不会浪费带宽。
不同的消费组可以这样用:最终清洗后的数据一方面进入流计算,另一方面入库保存。这种场景就适用于使用两个消费者组。
不同Topic的用法,对于不同类型的任务,使用不同的Topic。或者是相同任务不同消费周期,比如有个URL需要一天抓一次,有的需要1小时一次,这种场景就用不同的Topic来做。
针对Python而言,推荐用kafka-python这个包来与kafka做交互。实现一个简单的读写kafka模型很容易:
写入数据到kafka:
from kafka import KafkaProducer
producer = KafkaProducer(bootstrap_servers=['localhost:9092'])
producer.send('a-topic', b'some data')
从kafka指定topic读数据:
from kafka import KafkaConsumer
consumer = KafkaConsumer('a-topic',
group_id='some-group',
bootstrap_servers=['localhost:9092'])
for msg in consumer:
print(msg)
领取专属 10元无门槛券
私享最新 技术干货