arrow-left

All pages
gitbookPowered by GitBook
1 of 7

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Azure EventHub

Kafka

This page describes how to connect Kafka to Pinot

hashtag
Kafka 2.x Plugin

Pinot provides stream plugin support for Kafka 2.x version. Although the version used in this implementation is kafka 2.0.0, it’s possible to compile it with higher kafka lib version, e.g. 2.1.1.

hashtag
How to build and release Pinot package with Kafka 2.x connector

hashtag
How to use Kafka 2.x connector

  • Use Kafka Stream(High) Level Consumer

Below is a sample streamConfigs used to create a realtime table with Kafka Stream(High) level consumer.

Kafka 2.x HLC consumer uses org.apache.pinot.core.realtime.impl.kafka2.KafkaConsumerFactory in config stream.kafka.consumer.factory.class.name.

  • Use Kafka Partition(Low) Level Consumer

Below is a sample table config used to create a realtime table with Kafka Partition(Low) level consumer:

Please note:

  1. Config replicasPerPartition under segmentsConfig is required to specify table replication.

  2. Config stream.kafka.consumer.type should be specified as LowLevel to use partition level consumer. (The use of simple instead of LowLevel is deprecated)

hashtag
Upgrade from Kafka 0.9 connector to Kafka 2.x connector

  • Update table config for both high level and low level consumer: Update config: stream.kafka.consumer.factory.class.name from org.apache.pinot.core.realtime.impl.kafka.KafkaConsumerFactory to org.apache.pinot.core.realtime.impl.kafka2.KafkaConsumerFactory.

  • If using Stream(High) level consumer: Please also add config stream.kafka.hlc.bootstrap.server into tableIndexConfig.streamConfigs. This config should be the URI of Kafka broker lists, e.g.

hashtag
How to use this plugin with higher Kafka version?

This connector is also suitable for Kafka lib version higher than 2.0.0. In pinot-connector-kafka-2.0/pom.xml change the kafka.lib.version from 2.0.0 to 2.1.1 will make this Connector working with Kafka 2.1.1.

  • Configs stream.kafka.zk.broker.url and stream.kafka.broker.list are required under tableIndexConfig.streamConfigs to provide kafka related information.

  • localhost:9092
    .
    mvn clean package -DskipTests -Pbin-dist -Dkafka.version=2.0
    "streamConfigs": {
      "streamType": "kafka",
      "stream.kafka.consumer.type": "highLevel",
      "stream.kafka.topic.name": "meetupRSVPEvents",
      "stream.kafka.decoder.class.name": "org.apache.pinot.core.realtime.impl.kafka.KafkaJSONMessageDecoder",
      "stream.kafka.hlc.zk.connect.string": "localhost:2191/kafka",
      "stream.kafka.consumer.factory.class.name": "org.apache.pinot.core.realtime.impl.kafka2.KafkaConsumerFactory",
      "stream.kafka.zk.broker.url": "localhost:2191/kafka",
      "stream.kafka.hlc.bootstrap.server": "localhost:19092"
    }
    {
      "tableName": "meetupRsvp",
      "tableType": "REALTIME",
      "segmentsConfig": {
        "timeColumnName": "mtime",
        "timeType": "MILLISECONDS",
        "segmentPushType": "APPEND",
        "segmentAssignmentStrategy": "BalanceNumSegmentAssignmentStrategy",
        "schemaName": "meetupRsvp",
        "replication": "1",
        "replicasPerPartition": "1"
      },
      "tenants": {},
      "tableIndexConfig": {
        "loadMode": "MMAP",
        "streamConfigs": {
          "streamType": "kafka",
          "stream.kafka.consumer.type": "LowLevel",
          "stream.kafka.topic.name": "meetupRSVPEvents",
          "stream.kafka.decoder.class.name": "org.apache.pinot.core.realtime.impl.kafka.KafkaJSONMessageDecoder",
          "stream.kafka.consumer.factory.class.name": "org.apache.pinot.core.realtime.impl.kafka2.KafkaConsumerFactory",
          "stream.kafka.zk.broker.url": "localhost:2191/kafka",
          "stream.kafka.broker.list": "localhost:19092"
        }
      },
      "metadata": {
        "customConfigs": {}
      }
    }

    Amazon Kinesis

    Streaming

    hashtag
    Pluggable Streams

    Note

    This section is a pre-read if you are planning to develop plug-ins for streams other than Kafka. Pinot supports Kafka out of the box.

    Prior to commit ba9f2darrow-up-right, Pinot was only able to support consuming from Kafkaarrow-up-right stream.

    Pinot now enables its users to write plug-ins to consume from pub-sub streams other than Kafka. (Please refer to )

    Some of the streams for which plug-ins can be added are:

    You may encounter some limitations either in Pinot or in the stream system while developing plug-ins. Please feel free to get in touch with us when you start writing a stream plug-in, and we can help you out. We are open to receiving PRs in order to improve these abstractions if they do not work for a certain stream implementation.

    Refer to for details on how Pinot consumes streaming data.

  • Issue #2583arrow-up-right
    Amazon kinesisarrow-up-right
    Azure Event Hubsarrow-up-right
    LogDevicearrow-up-right
    Consuming and Indexing rows in Realtimearrow-up-right
    Pravegaarrow-up-right
    Pulsararrow-up-right

    Google Pub/Sub

    Write your stream

    This page describes how to write your own streams to plug to Pinot. Two modes are available: high and low level.

    hashtag
    Requirements to support Stream Level (High Level) consumers

    The stream should provide the following guarantees:

    • Exactly once delivery (unless restarting from a checkpoint) for each consumer of the stream.

    • (Optionally) support mechanism to split events (in some arbitrary fashion) so that each event in the stream is delivered exactly to one host out of set of hosts.

    • Provide ways to save a checkpoint for the data consumed so far. If the stream is partitioned, then this checkpoint is a vector of checkpoints for events consumed from individual partitions.

    • The checkpoints should be recorded only when Pinot makes a call to do so.

    • The consumer should be able to start consumption from one of:

      • latest avaialble data

      • earliest available data

    hashtag
    Requirements to support Partition Level (Low Level) consumers

    While consuming rows at a partition level, the stream should support the following properties:

    • Stream should provide a mechanism to get the current number of partitions.

    • Each event in a partition should have a unique offset that is not more than 64 bits long.

    • Refer to a partition as a number not exceeding 32 bits long.

    In addition, we have an operational requirement that the number of partitions should not be reduced over time.

    hashtag
    Stream plug-in implementation

    In order to add a new type of stream (say, Foo) implement the following classes:

    1. FooConsumerFactory extends

    2. FooPartitionLevelConsumer implements

    3. FooStreamLevelConsumer implements

    Depending on stream level or partition level, your implementation needs to include StreamLevelConsumer or PartitionLevelConsumer.

    The properties for the stream implementation are to be set in the table configuration, inside section.

    Use the streamType property to define the stream type. For example, for the implementation of stream foo, set the property "streamType" : "foo".

    The rest of the configuration properties for your stream should be set with the prefix "stream.foo". Be sure to use the same suffix for: (see examples below):

    • topic

    • consumer type

    • stream consumer factory

    All values should be strings. For example:

    You can have additional properties that are specific to your stream. For example:

    In addition to these properties, you can define thresholds for the consuming segments:

    • rows threshold

    • time threshold

    The properties for the thresholds are as follows:

    An example of this implementation can be found in the , which is an implementation for the kafka stream.

    last saved checkpoint

    Stream should provide the following mechanisms to get an offset for a given partition of the stream:

    • get the offset of the oldest event available (assuming events are aged out periodically) in the partition.

    • get the offset of the most recent event published in the partition

    • (optionally) get the offset of an event that was published at a specified time

  • Stream should provide a mechanism to consume a set of events from a partition starting from a specified offset.

  • Pinot assumes that the offsets of incoming events are monotonically increasing; i.e., if Pinot consumes an event at offset o1, then the offset o2 of the following event should be such that o2 > o1.

  • FooMetadataProvider implements StreamMetadataProviderarrow-up-right

  • FooMessageDecoder implements StreamMessageDecoderarrow-up-right

  • offset
  • decoder class name

  • decoder properties

  • connection timeout

  • fetch timeout

  • StreamConsumerFactoryarrow-up-right
    PartitionLevelConsumerarrow-up-right
    StreamLevelConsumerarrow-up-right
    streamConfigsarrow-up-right
    KafkaConsumerFactoryarrow-up-right
    "streamType" : "foo",
    "stream.foo.topic.name" : "SomeTopic",
    "stream.foo.consumer.type": "LowLevel",
    "stream.foo.consumer.factory.class.name": "fully.qualified.pkg.ConsumerFactoryClassName",
    "stream.foo.consumer.prop.auto.offset.reset": "largest",
    "stream.foo.decoder.class.name" : "fully.qualified.pkg.DecoderClassName",
    "stream.foo.decoder.prop.a.decoder.property" : "decoderPropValue",
    "stream.foo.connection.timeout.millis" : "10000", // default 30_000
    "stream.foo.fetch.timeout.millis" : "10000" // default 5_000
    "stream.foo.some.buffer.size" : "24g"
    "realtime.segment.flush.threshold.size" : "100000"
    "realtime.segment.flush.threshold.time" : "6h"

    Creating Pinot Segments

    hashtag
    Realtime segment generation

    To consume in realtime, we simply need to create a table with the same name as the schema and point to the Kafka topic to consume from, using a table definition such as this one:

    {
      "tableName": "flights",
      "tableType": "REALTIME",
      "segmentsConfig": {
        "retentionTimeUnit": "DAYS",
        "retentionTimeValue": "7",
        "segmentPushFrequency": "daily",
        "segmentPushType": "APPEND",
        "replication": "1",
        "timeColumnName": "daysSinceEpoch",
        "timeType": "DAYS",
        "segmentAssignmentStrategy": "BalanceNumSegmentAssignmentStrategy"
      },
      "tableIndexConfig": {
        "invertedIndexColumns": [
          "flightNumber",
          "tags",
          "daysSinceEpoch"
        ],
        "loadMode": "MMAP",
        "streamConfigs": {
          "streamType": "kafka",
          "stream.kafka.consumer.type": "highLevel",
          "stream.kafka.topic.name": "flights-realtime",
          "stream.kafka.decoder.class.name": "org.apache.pinot.core.realtime.impl.kafka.KafkaJSONMessageDecoder",
          "stream.kafka.zk.broker.url": "localhost:2181",
          "stream.kafka.hlc.zk.connect.string": "localhost:2181"
        }
      },
      "tenants": {
        "broker": "brokerTenant",
        "server": "serverTenant"
      },
      "metadata": {
      }
    }

    First, we’ll start a local instance of Kafka and start streaming data into it:Untitled

    This will stream one event per second from the Avro file to the Kafka topic. Then, we’ll create a realtime table, which will start consuming from the Kafka topic.

    We can then query the table with the following query to see the events stream in:

    Repeating the query multiple times should show the events slowly being streamed into the table.

    bin/pinot-admin.sh StartKafka &
    bin/pinot-admin.sh StreamAvroIntoKafka -avroFile flights-2014.avro -kafkaTopic flights-realtime &
    bin/pinot-admin.sh AddTable -filePath flights-definition-realtime.json
    SELECT COUNT(*) FROM flights