{"id":32707,"date":"2024-04-19T14:52:21","date_gmt":"2024-04-19T12:52:21","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/?p=32707"},"modified":"2024-09-06T14:00:17","modified_gmt":"2024-09-06T12:00:17","slug":"apache-kafka-and-ksqldb","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/","title":{"rendered":"Apache Kafka and ksqlDB"},"content":{"rendered":"\n<p>After two introduction blogs on Apache Kafka (ie. <a href=\"https:\/\/www.dbi-services.com\/blog\/apache-kafka-concepts-by-example\/\" target=\"_blank\" rel=\"noreferrer noopener\">Apache Kafka Concepts by Example<\/a> and <a href=\"https:\/\/www.dbi-services.com\/blog\/apache-kafka-consumer-group\/\" target=\"_blank\" rel=\"noreferrer noopener\">Apache Kafka Consumer Group<\/a>), it is time to discover the wide ecosystem around it. In this blog post, I will play with <a href=\"https:\/\/ksqldb.io\/overview.html\" target=\"_blank\" rel=\"noreferrer noopener\">ksqlDB<\/a>, streams and tables.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-ksqldb\">ksqlDB<\/h2>\n\n\n\n<p>ksqlDB is a server that takes benefit of an Apache Kafka infrastructure for real time data streaming. It can be used to capture events (via, for example, Kafka Connect), transform events, expose views (or tables).<\/p>\n\n\n\n<p>Starting ksqlDB server is easy. First, we need to set the bootstrap servers of our Kafka cluster in <code>etc\/ksqldb\/ksql-server.properties<\/code> file:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nbootstrap.servers=localhost:29092\n<\/pre><\/div>\n\n\n<p>As it is used for a proof of concept, I use a one broker cluster (ie. without high availability). Of course, ksqlDB server supports HA.<\/p>\n\n\n\n<p>The command to start:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nbin\/ksql-server-start etc\/ksqldb\/ksql-server.properties\n<\/pre><\/div>\n\n\n<p>And once, it up and running, you should see this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;2024-04-19 11:43:25,485] INFO Waiting until monitored service is ready for metrics collection (io.confluent.support.metrics.BaseMetricsReporter:173)\n&#x5B;2024-04-19 11:43:25,485] INFO Monitored service is now ready (io.confluent.support.metrics.BaseMetricsReporter:185)\n&#x5B;2024-04-19 11:43:25,485] INFO Attempting to collect and submit metrics (io.confluent.support.metrics.BaseMetricsReporter:144)\n&#x5B;2024-04-19 11:43:25,486] INFO ksqlDB API server listening on http:\/\/0.0.0.0:8088 (io.confluent.ksql.rest.server.KsqlRestApplication:385)\n\n                  ===========================================\n                  =       _              _ ____  ____       =\n                  =      | | _____  __ _| |  _ \\| __ )      =\n                  =      | |\/ \/ __|\/ _` | | | | |  _ \\      =\n                  =      |   &amp;lt;\\__ \\ (_| | | |_| | |_) |     =\n                  =      |_|\\_\\___\/\\__, |_|____\/|____\/      =\n                  =                   |_|                   =\n                  =        The Database purpose-built       =\n                  =        for stream processing apps       =\n                  ===========================================\n\nCopyright 2017-2022 Confluent Inc.\n\nServer 0.29.0 listening on http:\/\/0.0.0.0:8088\n\nTo access the KSQL CLI, run:\nksql http:\/\/0.0.0.0:8088\n\n&#x5B;2024-04-19 11:43:25,489] INFO Server up and running (io.confluent.ksql.rest.server.KsqlServerMain:153)\n&#x5B;2024-04-19 11:47:04,248] INFO Successfully submitted metrics to Confluent via secure endpoint (io.confluent.support.metrics.submitters.ConfluentSubmitter:146)\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"h-ksqldb-client\">ksqlDB Client<\/h2>\n\n\n\n<p>Now, we are ready to start the ksqlDB client:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nbin\/ksql http:\/\/localhost:8088\n<\/pre><\/div>\n\n\n<p>if all went well, you should receive the ksql prompt and see the server status as <mark class=\"has-inline-color has-luminous-vivid-orange-color\">RUNNING<\/mark>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n                  ===========================================\n                  =       _              _ ____  ____       =\n                  =      | | _____  __ _| |  _ \\| __ )      =\n                  =      | |\/ \/ __|\/ _` | | | | |  _ \\      =\n                  =      |   &amp;lt;\\__ \\ (_| | | |_| | |_) |     =\n                  =      |_|\\_\\___\/\\__, |_|____\/|____\/      =\n                  =                   |_|                   =\n                  =        The Database purpose-built       =\n                  =        for stream processing apps       =\n                  ===========================================\n\nCopyright 2017-2022 Confluent Inc.\n\nCLI v0.29.0, Server v0.29.0 located at http:\/\/localhost:8088\nServer Status: RUNNING\n\nHaving trouble? Type &#039;help&#039; (case-insensitive) for a rundown of how things work!\n\nksql&amp;gt;\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"h-stream\">Stream<\/h2>\n\n\n\n<p>One advantage, and a drawback as well, is that a Kafka topic (refer to my previous <a href=\"https:\/\/www.dbi-services.com\/blog\/apache-kafka-concepts-by-example\/\" target=\"_blank\" rel=\"noreferrer noopener\">blog post<\/a> if you don&#8217;t know what this is) can store anything and each message can have its own format (text or binary). <a href=\"https:\/\/docs.confluent.io\/platform\/current\/schema-registry\/index.html\" target=\"_blank\" rel=\"noreferrer noopener\">Schema Registry<\/a> can enforce formatting rules, versioning and serialization\/de-serialization information (I will cover that in another blog). ksql also enforces the formatting when defining a stream. For example, I create a order stream with 4 fields:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>order id<\/li>\n\n\n\n<li>customer id<\/li>\n\n\n\n<li>product id<\/li>\n\n\n\n<li>status<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nksql&gt; create stream order_stream (order_id int, customer_id int, product_id int, status_id int)\nwith (kafka_topic=&#039;order_topic&#039;,value_format=&#039;json&#039;,partitions=1);\n\n Message\n----------------\n Stream created\n----------------\n<\/pre><\/div>\n\n\n<p>To check what happened in the background, I could either use <a href=\"https:\/\/github.com\/provectus\/kafka-ui\" target=\"_blank\" rel=\"noreferrer noopener\">Kafka UI<\/a> or even ksql:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nksql&gt; show streams;\n\n Stream Name         | Kafka Topic                 | Key Format | Value Format | Windowed\n------------------------------------------------------------------------------------------\n KSQL_PROCESSING_LOG | default_ksql_processing_log | KAFKA      | JSON         | false\n ORDER_STREAM        | order_topic                 | KAFKA      | JSON         | false\n------------------------------------------------------------------------------------------\nksql&gt; show topics;\n\n Kafka Topic                 | Partitions | Partition Replicas\n---------------------------------------------------------------\n default_ksql_processing_log | 1          | 1\n order_topic                 | 1          | 1\n---------------------------------------------------------------\nksql&gt;\n<\/pre><\/div>\n\n\n<p>We can see our stream and the associated backend topic.<\/p>\n\n\n\n<p>Let&#8217;s insert data in the stream:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\ninsert into order_stream (order_id, customer_id, product_id, status_id) values (1, 10, 21, 0);\n<\/pre><\/div>\n\n\n<p>And check data is there:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nksql&gt; select * from order_stream;\n+-----------------------+-----------------------+-----------------------+-----------------------+\n|ORDER_ID               |CUSTOMER_ID            |PRODUCT_ID             |STATUS_ID              |\n+-----------------------+-----------------------+-----------------------+-----------------------+\n|1                      |10                     |21                     |0                      |\nQuery Completed\nQuery terminated\n<\/pre><\/div>\n\n\n<p>And in the topic, what is actually stored? We can run a <code>kafka-console-consumer.sh<\/code> to see it. By the way, command must be started <strong>before<\/strong> inserting data or with <code>--from-beginning<\/code> option:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n$ .\/kafka-console-consumer.sh --bootstrap-server localhost:29092 --topic order_topic\n{&quot;ORDER_ID&quot;:1,&quot;CUSTOMER_ID&quot;:10,&quot;PRODUCT_ID&quot;:21,&quot;STATUS_ID&quot;:0}\n<\/pre><\/div>\n\n\n<p>Every update of the order status will imply a new event in the order_stream.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-table\">Table<\/h2>\n\n\n\n<p>Let&#8217;s say we want to see the status name instead of the status id which has no meaning to us. It is possible to create a table which will contain both status_id and the associated status_name:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\ncreate table status (status_id int primary key, status_name varchar)\nwith (kafka_topic=&#039;status&#039;,value_format=&#039;json&#039;,partitions=1);\n<\/pre><\/div>\n\n\n<p>As you can see, when defining a table, we have to define a primary key. One of the main difference is when querying a table, only the last value of each primary key will be provided.<\/p>\n\n\n\n<p>Let&#8217;s insert some data into <mark class=\"has-inline-color has-luminous-vivid-orange-color\">status <\/mark>table:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\ninsert into status (status_id, status_name) values (0,&#039;Pending&#039;);\ninsert into status (status_id, status_name) values (1,&#039;Processing&#039;);\ninsert into status (status_id, status_name) values (2,&#039;Shipped&#039;);\ninsert into status (status_id, status_name) values (3,&#039;Delivered&#039;);\ninsert into status (status_id, status_name) values (4,&#039;Canceled&#039;);\n<\/pre><\/div>\n\n\n<p>And we can query it:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nksql&amp;gt; select * from status emit changes;\n+-------------------------------------------------+-------------------------------------------------+\n|STATUS_ID                                        |STATUS_NAME                                      |\n+-------------------------------------------------+-------------------------------------------------+\n|0                                                |Pending                                          |\n|1                                                |Processing                                       |\n|2                                                |Shipped                                          |\n|3                                                |Delivered                                        |\n|4                                                |Canceled                                         |\n<\/pre><\/div>\n\n\n<p>Oops, I see a typo in Canceled. How to correct it? By inserting a new record with the update:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\ninsert into status (status_id, status_name) values (4,&#039;Cancelled&#039;);\n<\/pre><\/div>\n\n\n<p>If I keep the select open, I will see the update and if I query it again, I see the fixed status_name:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nksql&gt; select * from status emit changes;\n+-------------------------------------------------+-------------------------------------------------+\n|STATUS_ID                                        |STATUS_NAME                                      |\n+-------------------------------------------------+-------------------------------------------------+\n|0                                                |Pending                                          |\n|1                                                |Processing                                       |\n|2                                                |Shipped                                          |\n|3                                                |Delivered                                        |\n|4                                                |Cancelled                                        |\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"h-joining-table-and-stream\">Joining Table and Stream<\/h2>\n\n\n\n<p>One interest of this is that you can join table and stream like in any SQL database to improve the result. The SQL query to create that stream is:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\ncreate stream order_stream_with_status as\n  select order_id, customer_id, order_stream.status_id, product_id, status.status_name as status_name\n  from order_stream left join status on order_stream.status_id = status.status_id\nemit changes;\n<\/pre><\/div>\n\n\n<p>Here I create a new stream (ie. order_stream_with_status) based on an stream <mark class=\"has-inline-color has-luminous-vivid-orange-color\">order_stream <\/mark>and joined to table <mark class=\"has-inline-color has-pale-cyan-blue-color\">status_name<\/mark>. &#8220;<code>emit changes<\/code>&#8221; is to see all changes (messages) from the topic.<\/p>\n\n\n\n<p>Let&#8217;s see what is happening while selecting from this new stream when inserting in order_stream:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\n select * from ORDER_STREAM_WITH_STATUS emit changes;\n+------------------+------------------+------------------+------------------+------------------+\n|ORDER_STREAM_STATU|ORDER_ID          |CUSTOMER_ID       |PRODUCT_ID        |STATUS_NAME       |\n|S_ID              |                  |                  |                  |                  |\n+------------------+------------------+------------------+------------------+------------------+\n|0                 |1                 |10                |21                |Pending           |\n<\/pre><\/div>\n\n\n<p>Great! Now, we see a status name. Of course, this can be done with other columns as well. We can even use Kafka Connect to get data from a database like MySQL or Postgres.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-filtered-stream\">Filtered Stream<\/h2>\n\n\n\n<p>Now, let&#8217;s say our shop bills customer when order has been shipped. Obviously, they don&#8217;t want to be notified on all events received in <mark class=\"has-inline-color has-luminous-vivid-orange-color\">order_stream<\/mark>, thus we can create a new stream which will filter on status_id=2. The sql query for that can be:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\ncreate stream order_stream_billing as\n select order_id, customer_id, order_stream.status_id, product_id, status.status_name as status_name\n from order_stream left join status on order_stream.status_id = status.status_id\n where order_stream.status_id=2\nemit changes;\n<\/pre><\/div>\n\n\n<p>We can insert few orders into order_stream:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\ninsert into order_stream (order_id, customer_id, product_id, status_id) values (1, 10, 21, 0);\ninsert into order_stream (order_id, customer_id, product_id, status_id) values (2, 10, 21, 0);\ninsert into order_stream (order_id, customer_id, product_id, status_id) values (3, 10, 21, 0);\ninsert into order_stream (order_id, customer_id, product_id, status_id) values (4, 10, 21, 0);\ninsert into order_stream (order_id, customer_id, product_id, status_id) values (5, 10, 21, 0);\n<\/pre><\/div>\n\n\n<p>And then update their status:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\ninsert into order_stream (order_id, customer_id, product_id, status_id) values (1, 10, 21, 1);\ninsert into order_stream (order_id, customer_id, product_id, status_id) values (2, 10, 21, 1);\ninsert into order_stream (order_id, customer_id, product_id, status_id) values (3, 10, 21, 2);\ninsert into order_stream (order_id, customer_id, product_id, status_id) values (4, 10, 21, 1);\ninsert into order_stream (order_id, customer_id, product_id, status_id) values (5, 10, 21, 2);\n<\/pre><\/div>\n\n\n<p>What will the select show? You guessed right, only two of them will be in the queue:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nselect * from ORDER_STREAM_billing emit changes;\n+------------------+------------------+------------------+------------------+------------------+\n|ORDER_STREAM_STATU|ORDER_ID          |CUSTOMER_ID       |PRODUCT_ID        |STATUS_NAME       |\n|S_ID              |                  |                  |                  |                  |\n+------------------+------------------+------------------+------------------+------------------+\n|2                 |3                 |10                |21                |Shipped           |\n|2                 |5                 |10                |21                |Shipped           |\n\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"h-and-in-the-infrastructure\">And in the Infrastructure?<\/h2>\n\n\n\n<p>While doing all these tests, I forgot to check what was happening on the pure Kafka side. Let&#8217;s see:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nksql&gt; show topics;\n\n Kafka Topic                 | Partitions | Partition Replicas\n---------------------------------------------------------------\n ORDER_STREAM_BILLING        | 1          | 1\n ORDER_STREAM_WITH_STATUS    | 1          | 1\n default_ksql_processing_log | 1          | 1\n order_topic                 | 1          | 1\n status                      | 1          | 1\n---------------------------------------------------------------\n<\/pre><\/div>\n\n\n<p>The two streams with upper case were created like that because topic name was not specified during the creation and, as per documentation, the upper case of table name is used as topic name.<\/p>\n\n\n\n<p>In short, ksqlDB is part of an Extract, Transform and Load (ETL) process.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After two introduction blogs on Apache Kafka (ie. Apache Kafka Concepts by Example and Apache Kafka Consumer Group), it is time to discover the wide ecosystem around it. In this blog post, I will play with ksqlDB, streams and tables. ksqlDB ksqlDB is a server that takes benefit of an Apache Kafka infrastructure for real [&hellip;]<\/p>\n","protected":false},"author":40,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197],"tags":[3064,702],"type_dbi":[],"class_list":["post-32707","post","type-post","status-publish","format-standard","hentry","category-application-integration-middleware","tag-apache-kafka","tag-etl"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Apache Kafka and ksqlDB - dbi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Apache Kafka and ksqlDB\" \/>\n<meta property=\"og:description\" content=\"After two introduction blogs on Apache Kafka (ie. Apache Kafka Concepts by Example and Apache Kafka Consumer Group), it is time to discover the wide ecosystem around it. In this blog post, I will play with ksqlDB, streams and tables. ksqlDB ksqlDB is a server that takes benefit of an Apache Kafka infrastructure for real [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2024-04-19T12:52:21+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-09-06T12:00:17+00:00\" \/>\n<meta name=\"author\" content=\"Middleware Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Middleware Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/\"},\"author\":{\"name\":\"Middleware Team\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d8563acfc6e604cce6507f45bac0ea1\"},\"headline\":\"Apache Kafka and ksqlDB\",\"datePublished\":\"2024-04-19T12:52:21+00:00\",\"dateModified\":\"2024-09-06T12:00:17+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/\"},\"wordCount\":729,\"commentCount\":0,\"keywords\":[\"Apache Kafka\",\"ETL\"],\"articleSection\":[\"Application integration &amp; Middleware\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/\",\"name\":\"Apache Kafka and ksqlDB - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\"},\"datePublished\":\"2024-04-19T12:52:21+00:00\",\"dateModified\":\"2024-09-06T12:00:17+00:00\",\"author\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d8563acfc6e604cce6507f45bac0ea1\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/www.dbi-services.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Apache Kafka and ksqlDB\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d8563acfc6e604cce6507f45bac0ea1\",\"name\":\"Middleware Team\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g\",\"caption\":\"Middleware Team\"},\"url\":\"https:\/\/www.dbi-services.com\/blog\/author\/middleware-team\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Apache Kafka and ksqlDB - dbi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/","og_locale":"en_US","og_type":"article","og_title":"Apache Kafka and ksqlDB","og_description":"After two introduction blogs on Apache Kafka (ie. Apache Kafka Concepts by Example and Apache Kafka Consumer Group), it is time to discover the wide ecosystem around it. In this blog post, I will play with ksqlDB, streams and tables. ksqlDB ksqlDB is a server that takes benefit of an Apache Kafka infrastructure for real [&hellip;]","og_url":"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/","og_site_name":"dbi Blog","article_published_time":"2024-04-19T12:52:21+00:00","article_modified_time":"2024-09-06T12:00:17+00:00","author":"Middleware Team","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Middleware Team","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/"},"author":{"name":"Middleware Team","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d8563acfc6e604cce6507f45bac0ea1"},"headline":"Apache Kafka and ksqlDB","datePublished":"2024-04-19T12:52:21+00:00","dateModified":"2024-09-06T12:00:17+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/"},"wordCount":729,"commentCount":0,"keywords":["Apache Kafka","ETL"],"articleSection":["Application integration &amp; Middleware"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/","url":"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/","name":"Apache Kafka and ksqlDB - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"datePublished":"2024-04-19T12:52:21+00:00","dateModified":"2024-09-06T12:00:17+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d8563acfc6e604cce6507f45bac0ea1"},"breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/apache-kafka-and-ksqldb\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Apache Kafka and ksqlDB"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d8563acfc6e604cce6507f45bac0ea1","name":"Middleware Team","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ddcae7ba0f9d1a0e7ae707f0e689e4a9c95bb48ec49c8e6d9cc86d43f4121cb6?s=96&d=mm&r=g","caption":"Middleware Team"},"url":"https:\/\/www.dbi-services.com\/blog\/author\/middleware-team\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/32707","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/40"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=32707"}],"version-history":[{"count":14,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/32707\/revisions"}],"predecessor-version":[{"id":32736,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/32707\/revisions\/32736"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=32707"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=32707"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=32707"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=32707"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}