kafka是由LinkedIn開發,主要是用來處理Linkedin的大面積活躍數據流處理(activity stream). 此類的數據經常用來反
映網站的一些有用的信息,比如PV,頁面展示給哪些用戶訪問,用戶搜索什麼關鍵字最多,這類信息經常被log到文件
裏,然後線下且週期性的去分析這些數據。現在這種用戶活躍數據已經成爲互聯網公司重要的一部分,所以必須構建
一個更輕量且更精煉的基礎架構。
活躍數據 使用案列
分析一下用戶行爲(pageviews),以便我能設計出更好的廣告位。
快速的統計用戶投票,點擊。
對用戶的搜索關鍵詞進行統計,分析出當前的流行趨勢。
防止用戶對網站進行無限制的抓取數據,以及超限制的使用API,辨別垃圾。
對網站進行全方位的實時監控,從而得到實時有效的性能數據,並且及時的發成警告。
活躍數據的特點
高流量的活躍數據是無法確定其大小的,因爲他可能隨時的變化,比如商家可能促銷,節假日打折,突然又冒出
一個跳樓價等等。所有的數據可能是數量級的往上遞增。 傳統日誌分析方式都是需要離線,而且操作起來比較複雜,
根本無法滿足實時的分析。另一方面,現有的消息隊列系統只能達到近似實時的分析,因爲無法消費大量的持久化在
隊列系統上的信息。Kafka的目標就是能夠成爲一個高效的隊列平臺,無論是處理離線的信息還是在線的信息。
kafka是一個消息訂閱和發佈的系統
我們將message的發佈(publish)者稱爲producer,將message的訂閱(subscribe)者稱爲consumer,將中間的存
儲陣列稱作broker。
kafka集羣
核心概念
1.topic (發佈的消息都存在於某個主題中)
2.partition (topic中的分區,爲了負載均衡)
3.offset (kafka的消費是依靠讀取每個消息的偏移量,並且消費完不立刻銷燬消息,可配置消息的生命週期)
4.consumer group
一個consumer group對於同一條消息只能消費一次
不同consumer group可以共享同一個消息,同樣每個group只能消費一次
kafka僞分佈式搭建
tar -zxvf kafka_2.10-0.8.1.1.tgz
#(啓動自帶的zookeeper)
啓動ZK bin/zookeeper-server-start.sh config/zookeeper.properties
#啓動kafka服務
啓動服務 bin/kafka-server-start.sh config/server.properties
#在地址爲localhost:2181的zookeeper上創建一個主題test,副本因子是1
創建主題 bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
#查看地址爲localhost:2181的zookeeper上所有主題
查看主題 bin/kafka-topics.sh --list --zookeeper localhost:2181
#查看test主題的詳細信息
bin/kafka-topics.sh --describe --zookeeper localhost:2181 --topic test
命令:
創建生產者 bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test
創建消費者 bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic test --from-beginning
在創建生產者的命令行輸入消息,即可在消費者命令行中顯示。
可以在僞分佈下啓動多個kafka服務(broker)
創建多個server.properties文件分別命名,啓動命令kafka-server-start.sh config/server.properties分別使用這幾個
server.properties文件。需要修改每個server.properties中的內容:
1.broker.id
2.port
3.log.dirs
保證每個broker服務的配置項是唯一,分別啓動。
kafka集羣搭建
修改server.properties文件
1.指定唯一的broker.id
2.host.name指定主機ip或者主機名
3.log.dirs指定一個日誌輸出目錄
將kafka配置信息複製到其他節點,分別修改broker.id和host.name
在各節點分別執行kafka-server-start.sh config/server.properties >/del/null 2>&1 &
以後臺進程啓動(&),並且將輸出送到垃圾箱(>/del/null),將錯誤信息也輸送到1的位置(垃圾箱)2>&1
package com.bigdata.hadoop.kafka;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import kafka.javaapi.producer.Producer;
import kafka.producer.KeyedMessage;
import kafka.producer.ProducerConfig;
import kafka.serializer.StringEncoder;
//創建生產者,每秒給主題test12發送一個消息
public class KafkaProducer extends Thread{
String topic = "test12";
String message = "hello world";
@Override
public void run() {
Properties originalProps = new Properties();
originalProps.put("serializer.class", StringEncoder.class.getName());
originalProps.put("metadata.broker.list", "hadoop4:9092,hadoop5:9092,hadoop6:9092");
Producer<Integer, String> producer = new Producer<Integer, String>(new ProducerConfig(originalProps));
int i = 0;
while (true) {
producer.send(new KeyedMessage<Integer, String>(topic, message + i++));
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new KafkaProducer().start();
}
}
package com.bigdata.hadoop.kafka;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import kafka.consumer.Consumer;
import kafka.consumer.ConsumerConfig;
import kafka.consumer.ConsumerIterator;
import kafka.consumer.KafkaStream;
import kafka.javaapi.consumer.ConsumerConnector;
//創建消費者,消費主題test12的消息
public class KafkaConsumer extends Thread{
String topic = "test12";
String message = "hello world";
@Override
public void run() {
Properties originalProps = new Properties();
originalProps.put("group.id", "group1");
originalProps.put("zookeeper.connect", "hadoop4:2181");
//創建消費者連接器
ConsumerConnector javaConsumerConnector = Consumer.createJavaConsumerConnector(new ConsumerConfig(originalProps));
Map<String, Integer> topicCountMap = new HashMap<String, Integer>();
topicCountMap.put(topic, 1);//消費topic 每次消費1條
//獲取指定topic的消息流
Map<String, List<KafkaStream<byte[], byte[]>>> messageStreams = javaConsumerConnector.createMessageStreams(topicCountMap);
KafkaStream<byte[], byte[]> stream = messageStreams.get(topic).get(0);
//迭代消息流中的消息
ConsumerIterator<byte[], byte[]> iterator = stream.iterator();
while (iterator.hasNext()) {
System.err.println(new String(iterator.next().message()));
}
}
public static void main(String[] args) {
new KafkaConsumer().start();
}
}