1.kafka是什么?
kafka是一个scala开发的消息队列,它的作用是解耦、异步、并发。
2.kafka中的概念有哪些?
producer:一或多个生产者向kafka中生产数据
consumer:一或多个消费者从kafka中拉取数据,消费者不关心谁生产的数据,消费后不删除队列中数据;
broker:代理人或者拉皮条的,kafka中
一台服务器或者说是一台机器上用于管理磁盘上存储数据的
进程(数据太多存在内存放不下,所以会有存在磁盘上);
consumerGroup:用来实现一个topic消息的
广播(发给所有的consumer)和
单播(发给任意一个consumer)。如果需要实现广播,只要每个consumer有一个独立的consumerGroup就可以了。要实现单播只要所有的consumer在同一个consumerGroup,在同一个组内多个消费者线程消费同一个topic数据,组员之间不能重复消费。
Topic:目的地,这是一个逻辑上的概念,落到磁盘上是一个partition的目录。partition的目录中有多个segment。一个Topic对应多个partition,一个partition对应多个segment。一个segment有默认的大小是1G。每个partition可以设置多个副本(replication),会从所有的副本中选取一个leader出来。所有读写操作都是通过
leader来进行的。
offset:每个partition都由一系列有序的、不可变的message组成,这些消息被连续的追加到partition中。offset表示一个parition已经消费了多少条message。
Lag:表示一个parition有多少条message没有被消费,用于查看Kafka Consumer的消费延迟情况,通过HW(Consumer可见的Offset)-Current_Offset(Consumer消费到的具体Offset)。
3.kafka中zookeeper的主要作用?
- 管理broker:每个Broker启动时,都会到zookeeper上进行注册,在/brokers/ids目录下创建临时节点,然后将IP地址和端口信息记录到该节点中;
- 维护分区信息与Broker的对应关系:比如临时节点/brokers/topics/login/3->2,表示Broker ID为3的一个broker,提供了2个分区用于对"login"这个Topic的消息存储;
- 存储消费的状态信息(低版本的 kafka):比如消费进度Offset,分区消息的消费进度Offset会定时地被记录到Zookeeper上,该消息分区在消费者下次重新消费时,保证能从之前的进度开始进行消费,然而由于Zookeeper自身存在一些问题比如单点故障,高版本的Kafka已经弱化了Zookeeper的这项功能,使用Kafka单独创建一个Topic存储消费信息;
。。。。。。当然zk还有其他一些功能,此处暂时先不深究了
4.kafka如何保证数据的完全生产?
通过ack机制:broker对发来的数据已确认接收无误,表示数据已经保存到
磁盘,
0:producer只管发,不等待broker返回确认消息,
1:producer等待topic中partition leader保存成功的状态反馈,
-1:producer等待topic中partition 所有副本都保存成功的状态反馈。
5.consumerGroup中的组员和partition之间如何做负载均衡?
最好是一一对应,因为一个组内的数据与分片数对应,所以最好一个分片(partition)对应一个组中的消费成员(consumer),成员太多,必然会有空闲。
6. kafka工具
KafkaManager
7.kafka常用命令(来自官网)
- 创建topic
1 bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
- 显示topic
1 bin/kafka-topics.sh --list --zookeeper localhost:2181
- 开启生产者
1 bin/kafka-console-producer.sh --broker-list localhost:9092 --topic my-replicated-topic
- 开启消费者
1 bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --from-beginning --topic my-replicated-topic
-
显示每个分区lag和偏移量信息
1 kafka-consumer-offset-checker --zookeeper 1.1.1.1:2181/aaa --topic xxxx --group group_id
结果显示为:
1 Group Topic Pid Offset logSize Lag Owner
- 查看单个分区的修改时间、偏移量(另外还有创建时间ctime、修改时间mtime)
1 get /目录/consumers/group_id/offsets/topic名/分区名
设置的话直接用
1 set /目录/consumers/group_id/offsets/topic名/分区名 值
8. kafka的一些特点
- kafka没有提供额外的索引机制来存储offset,所以在kafka中几乎不允许对消息进行“随机读写”;
- kafka和JMS(Java Message Service)实现(activeMQ)不同的是:即使消息被消费,消息仍然不会被立即删除。将会根据broker中的配置要求,保留一定的时间之后删除,释放磁盘空间,比如:
1 log.retention.hours=12 #数据最多保存12小时 2 log.retention.bytes=1073741824 #数据最多1G
9. storm整合kafka(参见博客)
- storm消费kafka
在创建KafkaSpout对象之前,必须先准备一个SpoutConfig对象。KafkaSpout是
kafka消费者与
storm的spout数据源的一个整合类,目的是让kafka的消费数据直接作为storm的数据源进行数据处理。而SpoutConfig是spout的一个配置类,配置kafka的各种信息,包括节点、端口、主题等等。
1 TopologyBuilder builder = new TopologyBuilder(); 2 BoltDeclarer generateDeclarer = 3 builder.setBolt("generate", new CommonGenerateBolt(), generateParallelHint); 4 5 final SpoutConfig viewSpout = getSpoutConfig(viewTopic, yconfig, ComponentType.VIEW); 6 KafkaSpout viewKafkaSpout = new KafkaSpout(viewSpout); 7 builder.setSpout("view-spout", viewKafkaSpout, viewSpoutParallelHint);
- storm写入kafka
1 public class ToKafkaBolt extends BaseRichBolt{ 2 private static final Logger Log = LoggerFactory.getLogger(ToKafkaBolt.class); 3 4 public static final String TOPIC = "topic"; 5 public static final String KAFKA_BROKER_PROPERTIES = "kafka.broker.properties"; 6 7 private Producer producer; 8 private OutputCollector collector; 9 private TupleToKafkaMapper Mapper; 10 private KafkaTopicSelector topicselector; 11 12 public ToKafkaBolt withTupleToKafkaMapper(TupleToKafkaMapper mapper){ 13 this.Mapper = mapper; 14 return this; 15 } 16 17 public ToKafkaBolt withTopicSelector(KafkaTopicSelector topicSelector){ 18 this.topicselector = topicSelector; 19 return this; 20 } 21 22 @Override 23 public void prepare(Map stormConf, TopologyContext context, 24 OutputCollector collector) { 25 26 if (Mapper == null) { 27 this.Mapper = new FieldNameBasedTupleToKafkaMapper(); 28 } 29 30 if (topicselector == null) { 31 this.topicselector = new DefaultTopicSelector((String)stormConf.get(TOPIC)); 32 } 33 34 Map configMap = (Map) stormConf.get(KAFKA_BROKER_PROPERTIES); 35 Properties properties = new Properties(); 36 properties.putAll(configMap); 37 ProducerConfig config = new ProducerConfig(properties); 38 producer = new Producer(config); 39 this.collector = collector; 40 } 41 42 @Override 43 public void execute(Tuple input) { 44 // String iString = input.getString(0); 45 K key = null; 46 V message = null; 47 String topic = null; 48 try { 49 key = Mapper.getKeyFromTuple(input); 50 message = Mapper.getMessageFromTuple(input); 51 topic = topicselector.getTopic(input); 52 if (topic != null) { 53 producer.send(new KeyedMessage(topic,message)); 54 }else { 55 Log.warn("skipping key = "+key+ ",topic selector returned null."); 56 } 57 } catch ( Exception e) { 58 // TODO: handle exception 59 Log.error("Could not send message with key = " + key 60 + " and value = " + message + " to topic = " + topic, e); 61 }finally{ 62 collector.ack(input); 63 } 64 } 65 @Override 66 public void declareOutputFields(OutputFieldsDeclarer declarer) { 67 } 68 }