kafka的安装和使用

kafka的介绍

 Apache Kafka是分布式发布-订阅消息系统,在 kafka官网上对 kafka 的定义:一个分布式 发布-订阅消息传递系统。 它最初由LinkedIn公司开发,Linkedin于2010年贡献给了Apache 基金会并成为顶级开源项目。Kafka是一种快速、可扩展的、设计内在就是分布式的,分区的 和可复制的提交日志服务。 注意:Kafka并没有遵循JMS规范,它只提供了发布和订阅通讯方式。 kafka中文官网:http://kafka.apachecn.org/quickstart.html

kafka的优点

高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, consumer group 对partition进行consume操作。 可扩展性:kafka集群支持热扩展 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败) 高并发:支持数千个客户端同时读写

kafka的相关名称

Broker:Kafka节点,一个Kafka节点就是一个broker,多个broker可以组成一个Kafka集群

Topic:一类消息,消息存放的目录即主题,例如page view日志、click日志等都可以以topic的形式存在,Kafka集群能够同时负责多个topic的分发

massage: Kafka中最基本的传递对象。

Partition:topic物理上的分组,一个topic可以分为多个partition,每个partition是一个有序的队列(分区)

Segment:partition物理上由多个segment组成,每个Segment存着message信息

Producer : 生产者,生产message发送到topic

Consumer : 消费者,订阅topic并消费message, consumer作为一个线程来消费 Consumer Group:消费者组,一个Consumer Group包含多个consumer

Offset:偏移量,理解为消息partition中的索引即可

kafka存储策略

kafka以topic来进行消息管理,每个topic包含多个partition,每个partition对应一个逻辑log,有多个segment组成。 每个segment中存储多条消息(见下图),消息id由其逻辑位置决定,即从消息id可直 接定位到消息的存储位置,避免id到位置的额外映射。 每个part在内存中对应一个index,记录每个segment中的第一条消息偏移。 发布者发到某个topic的消息会被均匀的分布到多个partition上(或根据用户指定的路由 规则进行分布),broker收到发布消息往对应partition的最后一个segment上添加该消息, 当某个segment上的消息条数达到配置值或消息发布时间超过阈值时,segment上的消息会被 flush到磁盘,只有flush到磁盘上的消息订阅者才能订阅到, segment达到一定的大小后将不会再往该segment写数据,broker会创建新的segment。

安装

因为kafka他是依赖于zookeeper所以一般在kafka之前必须先安装zookeeper

安装zookeeper(集群条件下)

1: 检查服务器上是否带有jdk环境(java -version),没有就进行安装

2: 下载并且安装zookeeper安装包

3: 解压zookeeper安装包 tar -zxvf zookeeper-3.4.10.tar.gz 重命名 mv zookeeper-3.4.10 zookeeper

4: 修改zoo_sample.cfg文件 cd /usr/local/zookeeper/conf mv zoo_sample.cfg zoo.cfg 修改conf: vi zoo.cfg 修改两处 修改路径 dataDir=/usr/local/zookeeper/data(注意同时在zookeeper创建data目录) 在zoo.cfg添加本机ip server.1=192.168.212.174:2888:3888 //其他服务器的IP地址 server.2=192.168.212.175:2888:3888 server.3=192.168.212.175:2888:3888

5: 创建服务器标识 在上面配置的dataDir对应路径创建data目录 创建文件夹: mkdir data 创建文件myid并填写内容为0: vi myid (内容为服务器标识 : 0)

6. 关闭每台服务器节点防火墙,systemctl stop firewalld.service 启动zookeeper 路径 /usr/local/zookeeper/bin ./zkServer.sh start 然后查看状态 zkServer.sh status(在三个节点上检验zk的mode,一个leader和俩个follower) 关闭指令 zkServer.sh stop

安装kafka

成功之后我们就可以安装kafka

下载kafka // 解压下载好的kafka压缩包并重命名 cd /usr/local wget http://mirror.bit.edu.cn/apache/kafka/1.0.0/kafka_2.11-1.0.0.tgz

解压 tar -zxvf kafka_2.11-1.0.0.tgz 重命名 mv kafka_2.12-0.11.0.0 kafka

// 修改配置文件server.properties

vi ./kafka/config/server.properties broker.id=0

//本机ip listeners=PLAINTEXT://192.168.131.130:9092

zookeeper的ip(如果是集群的话那么就以逗号隔开) zookeeper.connect=192.168.131.130:2181

在系统环境中配置kafka和zookeeper的路径

vi /etc/profile export JAVA_HOME=jdk的路径

export ZPPKEEPER_HOME=(你的zookeeper的路径)/usr/local/zookeeper

export KAFKA_HOME=(你的kafka的路径)/usr/local/kafka

export CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib export PATH=$JAVA_HOME/bin:${KAFKA_HOME}/bin:${ZPPKEEPER_HOME}/bin:$PATH

//配置文件生效 source /etc/profile

启动kafka的指令(启动之前检查zookeeper是否启动)

./bin/kafka-server-start.sh -daemon config/server.properties

创建一个分区(如果kafka创建集群的话多个分区会被平摊在不同的服务器上)

bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test

查看已经创建好的topic信息 bin/kafka-topics.sh --list --zookeeper localhost:2181

我们可以生产消息和消费消息了 生产者 这里不能用localhost应该用ip

bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test

这里不能用localhost应该用ip 消费者 bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning

关闭kafka ./bin/kafka-server-stop.sh -daemon config/server.properties

这样就完成了kafka的安装

package com.kafla.example.sc;

import java.util.Properties;

import com.kafla.example.util.Config;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;

/**
 * @Author ffc
 * @Description //TODO 生产者发送消息
 **/
public class KafkaProducerSc {

    private final KafkaProducer<String, String> producer;

    public KafkaProducerSc() {
        Properties props = new Properties();
        //读取kafka配置文件中的kafka的ip地址
        props.put("bootstrap.servers", Config.config.getProperty("bootstrap-servers"));
        // 批量抓取的大小
        props.put("batch.size", Config.config.getProperty("batch-size"));
        // 缓存容量
        props.put("buffer.memory", Config.config.getProperty("buffer-memory"));
        // key/value的反序列化
        props.put("key.serializer", StringSerializer.class.getName());
        props.put("value.serializer", StringSerializer.class.getName());
        this.producer = new KafkaProducer<String, String>(props);
    }

    public void run( String topic, String key, String value ) throws Exception {
        // topic: 消息队列的名称,可以先行在kafka服务中进行创建。如果kafka中并未创建该topic,那么便会自动创建!
        // key:键值,也就是value对应的值,和Map类似。
        // value:要发送的数据,数据格式为String类型的。
        producer.send(new ProducerRecord<String, String>(topic, key, value));
    }

    public static void main( String args[] ) {
        KafkaProducerSc kafkaProducerSc = new KafkaProducerSc();
        try {
            for (int i = 0; i < 10; i++) {
                System.out.println("发送了" + 1 + "条数据");
                kafkaProducerSc.run("xxxx", "key" + i, "值" + i+"润博");
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e);
        } finally {
            // 注意:生产者发送数据完了之后一定要把producer给关掉,否则数据发送不出去
            kafkaProducerSc.producer.close();
        }
    }
}



package com.kafla.example.sc;

import java.time.Duration;
import java.util.Properties;

import com.kafla.example.util.Config;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringDeserializer;

import java.util.Arrays;
import java.util.Properties;

/**
 * 2 * @Author: ffc
 * 3 * @Date: 2019/9/6 0:16
 * 消费者消费消息
 * 4
 */
public class KafkaConsumerSc {

    private final KafkaConsumer<String, String> consumer;
    private ConsumerRecords<String, String> msgList;

    public KafkaConsumerSc() {
        Properties props = new Properties();
        //设置kafka的ip
        props.put("bootstrap.servers", Config.config.getProperty("bootstrap-servers"));
        //消费者组
        props.put("group.id", Config.config.getProperty("group-id"));
        props.put("auto.offset.reset", Config.config.getProperty("auto-offset-reset"));
        // key/value的反序列化
        props.put("key.deserializer", StringDeserializer.class.getName());
        props.put("value.deserializer", StringDeserializer.class.getName());
        this.consumer = new KafkaConsumer<String, String>(props);

    }

    public void run( String topicName ) {
        int messageNo = 1;
        //设置主题
        consumer.subscribe(Arrays.asList(topicName));
        System.out.println("---------开始消费---------");
        try {
            for (; ; ) {
                // 获取ConsumerRecords,一秒钟轮训一次
                msgList = consumer.poll(1000);
                if (null != msgList && msgList.count() > 0) {
                    for (ConsumerRecord<String, String> record : msgList) {
                        // 接受并打印生产者发送过来的消息
                        System.out.println(messageNo + "=======receive: key = " + record.key() + ", value = " + record.value() + " offset===" + record.offset());
                        messageNo++;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            consumer.close();
        }
    }

    public static void main( String args[] ) {
        new KafkaConsumerSc().run("xxxxxx");
    }
}

 

 

 

# kafka服务器地址(可以多个以逗号分开)
bootstrap-servers=xxxxxxxxxxx:9092
#指定一个默认的组名(一个默认的组名,在kafka中一条消息可以被多个分组消费,但是只能被一个分组中的一个消费者消费。)自己定义
group-id=kafka2
# earliest:当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费
# latest:当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据
# none:topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常
auto-offset-reset=earliest
# key/value的反序列化
key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
# 批量抓取
batch-size=65536
# 缓存容量
buffer-memory=524288
#acks:消息的确认机制,默认值是0。
#acks=0:如果设置为0,生产者不会等待kafka的响应。
#acks=1:这个配置意味着kafka会把这条消息写到本地日志文件中,但是不会等待集群中其他机器的成功响应。
#acks=all:这个配置意味着leader会等待所有的follower同步完成。这个确保消息不会丢失,除非kafka集群中所有机器挂掉。这是最强的可用性保证,但是效率比较低。
acks=all

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值