カフカの基本原則

ディレクトリ

例参照の一部を構築するためのアーキテクチャカフカカフカカフカ削除ストレージポリシー戦略カフカbrokerKafka DesignThe ProducerThe消費者のコピーについて(レプリケーション)ログの圧縮(ログコンパクション)DistributionZookeeper協調制御の開発環境

簡単な紹介

システムをサブスクライブ・メッセージング - Apacheのカフカが公開配布されています。もともとは、後にApacheプロジェクトの一部となったLinkedInの会社によって開発されました。カフカは高速で、スケーラブルな分散型設計はゾーニング、固有のものであり、ログサービスを複製することができ提出します。

カフカアーキテクチャ

そのアーキテクチャは、次のコンポーネントが含まれています。

トピック(トピック):メッセージ・フローの特定のタイプ。メッセージはバイトのペイロード(ペイロード)で、話題はカテゴリ名やシードメッセージ(フィード)の名前です。

生産者(プロデューサー):オブジェクトは、任意のニューストピックを発行できるようにすることです。

サービスエージェント(ブローカー):パブリッシュされたメッセージは、サーバのセットに格納されている、彼らは呼ばれているプロキシ(ブローカー)またはカフカクラスタ。

消費者(消費者):これらのメッセージの消費が掲載されているので、あなたは、1以上のトピック、およびブローカーからプルデータを購読することができます。

ファイルhttps://images2015.cnblogs.com/blog/434101/201605/434101-20160514145613421-1488903046.png

カフカのストレージ戦略

1)カフカメッセージ管理のためのトピックに、トピックを複数備え、各パーティションは、各論理パーティションは、セグメントの複数からなる、ログに対応します。

2)各セグメントを格納メッセージの複数(下記参照)、その論理的位置によって決定されたメッセージIDは、すなわち、追加のロケーションマッピングIDを回避するために、記憶場所にメッセージのメッセージIDから直接配置することができます。

3)メモリ内の一部に各インデックス対応は、最初のメッセージセグメントの各レコードは、オフセット。

4)メッセージ・トピックを送信するパブリッシャが均等)パーティション複数の分散(またはユーザーによって指定されたルールをルーティング配布され、ブローカは、対応するパーティションに解放メッセージの最後のセグメントで受信されたメッセージを追加しますセグメント上のニュース個数公開設定された値またはメッセージがしきい値を超えた達したときにセグメントが一定のサイズに達した後、セグメント上のメッセージは、ディスクへのフラッシュ、に加入する加入者にメッセージをディスクにのみフラッシュあろうセグメントは、ブローカーが新しいセグメントを作成し、書き込みデータにまで行くことはありません。

ファイルhttps://images2015.cnblogs.com/blog/434101/201605/434101-20160514145722812-631325437.png

カフカの削除ポリシー

1)前N日削除します。

2)最新のデータMGBを保持します。

カフカブローカー

他のメッセージシステムとは異なり、カフカブローカーはステートレスです。消費者が状態情報を維持する必要があります。この手段は、消費されています。この情報は、消費者自身によって維持ブローカーは(オフセットmanagerbroker管理があります)気にされていません。

エージェントは、消費者がメッセージのために使用されているかどうかわからないため、エージェントからのメッセージを削除するには、非常に困難になります。この問題へのカフカ革新的なソリューション、単純な時間ベースのSLAを保持ポリシーを適用されます。一定の時間をかけてメッセージ・ブローカは、自動的に削除されます場合は。

この革新的なデザインは、大きな利点を持って、消費者が故意に再び古いオフセット消費データにフォールバックすることができます。これは、キューの一般的な合意に違反し、それは、多くの消費者の基本的な機能であることが判明しました。

カフカデザイン

目標

1)高は、大量イベントストリーム処理をサポートするスループット

システムオフラインから2)支持荷重データ

3)低レイテンシ・メッセージ・システム

持久化

1)ローカルに永続化、ファイルシステムに依存します

2)データの永続性をログに

効率

使用「メッセージセット」合成メッセージ:1)「小IO問題」を解決します。「メッセージの塊」を使用して、サーバーがログに書き込まれます。メッセージブロックの大きい消費者を得ます。

2)解决”byte copying“:在producer、broker和consumer之间使用统一的binary message format。使用系统的pagecache。使用sendfile传输log,避免拷贝。

端到端的批量压缩(End-to-end Batch Compression)Kafka支持GZIP和Snappy压缩协议。

The Producer

负载均衡1)producer可以自定义发送到哪个partition的路由规则。默认路由规则:hash(key)%numPartitions,如果key为null则随机选择一个partition。

2)自定义路由:如果key是一个user id,可以把同一个user的消息发送到同一个partition,这时consumer就可以从同一个partition读取同一个user的消息。

异步批量发送批量发送:配置不多于固定消息数目一起发送并且等待时间小于一个固定延迟的数据。

The Consumer

consumer控制消息的读取。

Push vs Pull1)producer push data to broker,consumer pull data from broker2)consumer pull的优点:consumer自己控制消息的读取速度和数量。3)consumer pull的缺点:如果broker没有数据,则可能要pull多次忙等待,Kafka可以配置consumer long pull一直等到有数据。

Consumer Position1)大部分消息系统由broker记录哪些消息被消费了,但Kafka不是。2)Kafka由consumer控制消息的消费,consumer甚至可以回到一个old offset的位置再次消费消息。

Message Delivery Semantics三种:At most once—Messages may be lost but are never redelivered.At least once—Messages are never lost but may be redelivered.Exactly once—this is what people actually want, each message is delivered once and only once.Producer:有个”acks“配置可以控制接收的leader的在什么情况下就回应producer消息写入成功。

Consumer:读取消息,写log,处理消息。如果处理消息失败,log已经写入,则无法再次处理失败的消息,对应”At most once“。读取消息,处理消息,写log。如果消息处理成功,写log失败,则消息会被处理两次,对应”At least once“。读取消息,同时处理消息并把result和log同时写入。这样保证result和log同时更新或同时失败,对应”Exactly once“。

Kafka默认保证at-least-once delivery,容许用户实现at-most-once语义,exactly-once的实现取决于目的存储系统,kafka提供了读取offset,实现也没有问题。

复制(Replication)

1)一个partition的复制个数(replication factor)包括这个partition的leader本身。

2)所有对partition的读和写都通过leader。

3)Followers通过pull获取leader上log(message和offset)

4)如果一个follower挂掉、卡住或者同步太慢,leader会把这个follower从”in sync replicas“(ISR)列表中删除。

5)当所有的”in sync replicas“的follower把一个消息写入到自己的log中时,这个消息才被认为是”committed“的。

6)如果针对某个partition的所有复制节点都挂了,Kafka选择最先复活的那个节点作为leader(这个节点不一定在ISR里)。

日志压缩(Log Compaction)

1)针对一个topic的partition,压缩使得Kafka至少知道每个key对应的最后一个值。

2)压缩不会重排序消息。

3)消息的offset是不会变的。

4)消息的offset是顺序的。

Distribution

Consumer Offset Tracking

1)High-level consumer记录每个partition所消费的maximum offset,并定期commit到offset manager(broker)。

2)Simple consumer需要手动管理offset。现在的Simple consumer Java API只支持commit offset到zookeeper。

Consumers and Consumer Groups

1)consumer注册到zookeeper

2)属于同一个group的consumer(group id一样)平均分配partition,每个partition只会被一个consumer消费。

3)当broker或同一个group的其他consumer的状态发生变化的时候,consumer rebalance就会发生。

Zookeeper协调控制

1)管理broker与consumer的动态加入与离开。

このような負荷の複数一つコンシューマ・グループ内の消費者のサブスクリプションをバランシングすることをブローカトリガロードバランシングアルゴリズムに参加又は離脱する2)トリガ、ロードバランシング、消費者または。

3)各パーティションの消費者情報及び消費者関係のメンテナンス。

メーカーコード例:

import java.util.*;
import kafka.javaapi.producer.Producer;
import kafka.producer.KeyedMessage;
import kafka.producer.ProducerConfig;

public class TestProducer {

    public static void main(String[] args) {

        long events = Long.parseLong(args[0]);

        Random rnd = new Random();


        Properties props = new Properties();

        props.put("metadata.broker.list", "broker1:9092,broker2:9092 ");

        props.put("serializer.class", "kafka.serializer.StringEncoder");

        props.put("partitioner.class", "example.producer.SimplePartitioner");

        props.put("request.required.acks", "1");


        ProducerConfig config = new ProducerConfig(props);


        Producer<String, Stringproducer = new Producer<String, String(config);


        for (long nEvents = 0; nEvents < events; nEvents  ) {

               long runtime = new Date().getTime();

               String ip = “192.168.2.”   rnd.nextInt(255);

               String msg = runtime   “,www.example.com,”   ip;

               KeyedMessage<String, Stringdata = new KeyedMessage<String, String("page_visits", ip, msg);

               producer.send(data);

        }

        producer.close();

    }

}

パーティショニングコード:

import kafka.producer.Partitioner;
import kafka.utils.VerifiableProperties;


public class SimplePartitioner implements Partitioner {

    public SimplePartitioner (VerifiableProperties props) {

    }


    public int partition(Object key, int a_numPartitions) {

        int partition = 0;

        String stringKey = (String) key;

        int offset = stringKey.lastIndexOf('.');

        if (offset 0) {

           partition = Integer.parseInt( stringKey.substring(offset 1)) % a_numPartitions;

        }

       return partition;

  }

}

消費者のコードサンプル:

import kafka.consumer.ConsumerConfig;
import kafka.consumer.KafkaStream;
import kafka.javaapi.consumer.ConsumerConnector;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class ConsumerGroupExample {

    private final ConsumerConnector consumer;

    private final String topic;

    private  ExecutorService executor;


    public ConsumerGroupExample(String a_zookeeper, String a_groupId, String a_topic) {

        consumer = kafka.consumer.Consumer.createJavaConsumerConnector(

                createConsumerConfig(a_zookeeper, a_groupId));

        this.topic = a_topic;

    }


    public void shutdown() {

        if (consumer != null) consumer.shutdown();

        if (executor != null) executor.shutdown();

        try {

            if (!executor.awaitTermination(5000, TimeUnit.MILLISECONDS)) {

                System.out.println("Timed out waiting for consumer threads to shut down, exiting uncleanly");

            }

        } catch (InterruptedException e) {

            System.out.println("Interrupted during shutdown, exiting uncleanly");

        }

   }


    public void run(int a_numThreads) {

        Map<String, IntegertopicCountMap = new HashMap<String, Integer();

        topicCountMap.put(topic, new Integer(a_numThreads));

        Map<String, List<KafkaStream<byte[], byte[]consumerMap = consumer.createMessageStreams(topicCountMap);

        List<KafkaStream<byte[], byte[]streams = consumerMap.get(topic);

        // now launch all the threads

        executor = Executors.newFixedThreadPool(a_numThreads);


        // now create an object to consume the messages

        int threadNumber = 0;

        for (final KafkaStream stream : streams) {

            executor.submit(new ConsumerTest(stream, threadNumber));

            threadNumber  ;

        }

    }


    private static ConsumerConfig createConsumerConfig(String a_zookeeper, String a_groupId) {

        Properties props = new Properties();

        props.put("zookeeper.connect", a_zookeeper);

        props.put("group.id", a_groupId);

        props.put("zookeeper.session.timeout.ms", "400");

        props.put("zookeeper.sync.time.ms", "200");

        props.put("auto.commit.interval.ms", "1000");


        return new ConsumerConfig(props);

    }


    public static void main(String[] args) {

        String zooKeeper = args[0];

        String groupId = args[1];

        String topic = args[2];

        int threads = Integer.parseInt(args[3]);


        ConsumerGroupExample example = new ConsumerGroupExample(zooKeeper, groupId, topic);

        example.run(threads);


        try {

            Thread.sleep(10000);

        } catch (InterruptedException ie) {

        }

        example.shutdown();

    }

}

ConsumerTestテストクラス:

import kafka.consumer.ConsumerIterator;
import kafka.consumer.KafkaStream;


public class ConsumerTest implements Runnable {

    private KafkaStream m_stream;

    private int m_threadNumber;


    public ConsumerTest(KafkaStream a_stream, int a_threadNumber) {

        m_threadNumber = a_threadNumber;

        m_stream = a_stream;

    }


    public void run() {

        ConsumerIterator<byte[], byte[]it = m_stream.iterator();

        while (it.hasNext())

            System.out.println("Thread "   m_threadNumber   ": "   new String(it.next().message()));

        System.out.println("Shutting down Thread: "   m_threadNumber);

    }

}

ビルドに開発環境

https://cwiki.apache.org/confluence/display/KAFKA/Developerセットアップ

いくつかの例

https://cwiki.apache.org/confluence/display/KAFKA/0.8.0例プロデューサー

参照

https://www.cnblogs.com/luxiaoxun/p/5492646.html

https://kafka.apache.org/documentation.html

https://cwiki.apache.org/confluence/display/KAFKA/Index

公開された149元の記事 ウォン称賛66 ビュー120 000 +

おすすめ

転載: blog.csdn.net/weixin_38004638/article/details/104088520