anchor.diff:  - An *offset*: a big number describing the position of the message in the log
   
   When the key is provided, it is hashed and this hash is used to determine in which partition it should go.
  -Two messages with same key will end in the same partition.
  +Two messages with the same key will end in the same partition.
   Messages having the same key can be merged together by an optional background process called compaction.
   
   The key and the value can be of any type: `String`, `long`, `byte[]`...
   This is made possible by *serializers* and *deserializers* which are strategies to read and write anything from byte stream.
  -There are some provided (de)serializers for basic types, as well as some third party (de)serializers to handle complex types.
  +Some (de)serializers are provided for basic types,
  +and there are some third party (de)serializers to handle complex types.
   For example, it's possible to exchange plain objects written in https://github.com/confluentinc/schema-registry/tree/master/json-serializer[JSON] or Avro format.
   
   == Sending messages
  
positive.code: 
  For Java developers, until Kafka 0.8, there was only an intricate Scala API with Java bindings.
  Since 0.9 there is a pure Java API which makes things simpler.
  
  == Creating a Topic
  
  The *topic* is the place where messages are sent and where they are stored.
  A topic is split into multiple *partitions*.
  Each partition is usually placed on a different Kafka node.
  Each partition can be *replicated* many times in order to tolerate node failures.
  Among replicas, a leader is elected, it has the privilege of receiving messages first and sending messages to consumers.
  
  At topic is automatically created when the first message arrives.
  Alternatively, it may be manually created with the `kafka-topic.sh` command line tool:
  
  [source]
  
negative.code: ----
  <1> Connect to these Kafka connect nodes.
    Like the producer, it doesn't have to be the whole Kafka cluster.
  <2> Register this application (consumer group) as a consumer for this list of topics.
    In return, Kafka will assign some partitions to this consumer.
  <3> Try to pull messages from the broker.
  <4> Pulled messages are automatically acknowledged.
  
  In the above example, connecting to the broker, subscribing to one or more topics,
  and being assigned partitions takes time and is usually done once during application start-up.
  On the contrary, the `poll` method should be run in loop.
  It returns a batch of records whose size is controlled by the `max.poll.records` and `max.partition.fetch.bytes` settings.
  
  Unlike the producer, the consumer is not thread-safe.
  In order to consume records in parallel, each thread should have it's own consumer.
  
  == Acknowledging received messages
  
  The message acknowledgement is called *offset commit*,
  because Kafka keeps track of the offset of the last consumed message for each topic + partition + consumer group.
  
  In the previous example, the offsets were automatically and periodically committed to the broker.
  This auto commit is configurable through properties:
  
  [source,java]
  ----
  