{"id":337956,"date":"2022-09-05T15:00:50","date_gmt":"2022-09-05T15:00:50","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=337956"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=337956","title":{"rendered":"<span>\u0417\u0430\u043c\u0435\u0442\u043a\u0438 \u0434\u0430\u0442\u0430-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0430: \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f Kafka \u0438 PySpark<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"bordered full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d16\/d7c\/581\/d16d7c5815d4c390b0a3a9748d95a1c5.png\" width=\"1625\" height=\"917\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d16\/d7c\/581\/d16d7c5815d4c390b0a3a9748d95a1c5.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0442\u0435\u043c, \u0447\u044c\u044f \u0434\u0435\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0432\u044f\u0437\u0430\u043d\u0430 \u0441 Data Engineering, \u0438 \u0442\u0435\u043c, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u0441\u044f \u0441 \u044d\u0442\u043e\u0439 \u0441\u043b\u0430\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u0435\u0439. \u0412\u044b \u0443\u0437\u043d\u0430\u0435\u0442\u0435 \u043f\u0440\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 Kafka \u0441\u043e Structured Streaming, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0432\u043e\u0434\u044f\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043a\u0430\u043c\u0438 \u0438 \u0441\u043a\u043e\u043b\u044c\u0437\u044f\u0449\u0438\u043c \u043e\u043a\u043d\u043e\u043c.<\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u043d\u0434\u0440\u0435\u0439, \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0434\u0430\u0442\u0430-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u043c \u0438 \u043f\u043e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0443 \u0442\u0438\u043c\u043b\u0438\u0434\u043e\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438\u0437 \u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a\u043e\u0433\u043e \u0441\u0435\u043a\u0442\u043e\u0440\u0430. \u0417\u0430 \u043f\u043b\u0435\u0447\u0430\u043c\u0438 \u0443 \u043c\u0435\u043d\u044f \u0438 \u043c\u043e\u0438\u0445 \u043a\u043e\u043b\u043b\u0435\u0433 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043a\u0430\u0441\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f DWH \u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 ETL-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432. \u041d\u0430\u043c \u0432\u0441\u0435\u043c \u0441\u0442\u0430\u043b\u0438 \u0443\u0436\u0435 \u00ab\u0440\u043e\u0434\u043d\u044b\u043c\u0438\u00bb \u0442\u0430\u043a\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043a\u0430\u043a: Oracle, PostgreSQL, GreenPlum, Hive, Impala, YARN, Spark \u0438 Airflow (\u0438 \u043f\u0440\u043e\u0447\u0438\u0435 \u0431\u0438\u0433\u0434\u0430\u0442\u0430-\u043f\u043e\u043a\u0435\u043c\u043e\u043d\u044b), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u043b\u0438\u0441\u044c \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u043f\u0430\u043a\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445. \u0410 \u0432\u043e\u0442 \u0441 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u043c\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430\u043c\u0438 \u043d\u0430 \u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u043b\u043e\u0442\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0435\u0449\u0451 \u043d\u0435 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u043b\u043e\u0441\u044c. \u041d\u0430\u0448\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u044f\u043b\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u00ab\u043f\u043e\u0434 \u043a\u043b\u044e\u0447\u00bb \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0442\u0438\u043f\u0430 \u00abReal Time Marketing\u00bb \u2013 \u0432 \u043e\u043d\u043b\u0430\u0439\u043d \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c \u0438 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0431\u0430\u043d\u043a\u0435, \u0441\u0432\u0435\u0440\u044f\u0442\u044c\u0441\u044f \u0438 \u0434\u0436\u043e\u0439\u043d\u0438\u0442\u044c\u0441\u044f \u0441 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445, \u0447\u0442\u043e\u0431\u044b \u0432 \u0438\u0442\u043e\u0433\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0438 \u0432\u044b\u0433\u043e\u0434\u043d\u044b\u0435 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u0412 \u0445\u043e\u0434\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043c\u044b \u0432\u044b\u043d\u0435\u0441\u043b\u0438 \u043c\u043d\u043e\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u0434\u043b\u044f \u0441\u0435\u0431\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u0437\u0430\u0434\u0430\u0447\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0439\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0435\u0433\u043e \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u2013 \u0432\u0435\u0441\u044c\u043c\u0430 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0441\u0442\u0440\u0438\u043c\u0438\u043d\u0433\u043e\u0432\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041d\u043e\u0432\u044b\u043c \u0431\u044b\u043b\u043e \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f, \u0442\u0430\u043a \u0438 \u0441\u0430\u043c\u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438. \u041e\u0434\u043d\u0438\u043c\u0438 \u0438\u0437 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043e\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c Kafka \u0438 Spark Structured Streaming \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 Python, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u043d\u0430\u0431\u0438\u0442\u044b\u043c\u0438 \u0448\u0438\u0448\u043a\u0430\u043c\u0438 \u0438 \u0443\u043c\u043e\u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u043a\u0430\u0441\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u044d\u0442\u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0438\u0445 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c. \u0423\u0432\u0435\u0440\u0435\u043d, \u0434\u043b\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0445 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0438 \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442 \u043c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u043d\u0435\u0440\u0432\u043e\u0432. \u0412\u0435\u0434\u044c \u0432\u0440\u0435\u043c\u044f, \u043a\u0430\u043a \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u0441\u0430\u043c\u044b\u0439 \u0446\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u0441\u0443\u0440\u0441.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043d\u0430\u0447\u043d\u0443 \u0441 \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u041f\u0435\u0440\u0432\u043e\u0435, \u0441 \u0447\u0435\u043c \u043c\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u2013 \u044d\u0442\u043e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0432\u0435\u0440\u0441\u0438\u044f\u0445 Hadoop \u0438 Spark, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0431\u0430\u043d\u043a\u043e\u043c \u043d\u0430 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435. \u0411\u0435\u0437\u0443\u0441\u043b\u043e\u0432\u043d\u043e, \u043c\u044b \u0434\u0430\u043b\u0438 \u0441\u0432\u043e\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438, \u043d\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0441\u043b\u043e\u0432\u043e \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u0437\u0430 \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a\u043e\u043c. \u0411\u044b\u043b\u043e \u0434\u0432\u0430 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430: Spark 2.x \u0438 Spark 3.x. \u0412\u0434\u043e\u0431\u0430\u0432\u043e\u043a \u043a \u044d\u0442\u043e\u043c\u0443, \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0440\u0430\u043d\u0435\u0435 \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u043e\u0434\u0440\u044f\u0434\u0447\u0438\u043a\u043e\u043c \u0443\u0436\u0435 \u0431\u044b\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0436\u0435\u043b\u0430\u0435\u043c\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 RDD-\u0434\u0438\u0430\u043b\u0435\u043a\u0442\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0431\u0443\u0434\u0443 \u043e\u0442\u043a\u0440\u043e\u0432\u0435\u043d\u0435\u043d \u2013 \u0432\u0435\u0441\u044c\u043c\u0430 \u043d\u0435\u0434\u0440\u0443\u0436\u0435\u043b\u044e\u0431\u0435\u043d \u0441\u0432\u043e\u0438\u043c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u043e\u043c, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u043e\u0441\u043b\u0435 \u00ab\u0432\u0430\u043d\u0438\u043b\u044c\u043d\u043e\u0433\u043e\u00bb Spark SQL. \u041d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u043e\u0440\u043e\u043c \u0435\u0449\u0451 \u043d\u0435 \u0431\u044b\u043b\u043e \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0435\u0448\u0435\u043d\u043e, \u0432 \u043a\u0430\u043a\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 Spark \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u0432 \u043a\u0430\u043a\u043e\u0439 \u043c\u0430\u043d\u0435\u0440\u0435 \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442 \u043f\u0438\u0441\u0430\u0442\u044c. <\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b:<\/p>\n<ol>\n<li>\n<p>Kafka 2.X + Spark 3.x \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u0441 Kafka + Hadoop 3;<\/p>\n<\/li>\n<li>\n<p> Kafka 2.X + Spark 2.4 + \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u0441 Kafka + Hadoop 2 \u0438\u043b\u0438 3;<\/p>\n<\/li>\n<li>\n<p> Kafka 2.X + Spark 2.x \u043d\u0435 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u0441 Kafka  + Hadoop 2;<\/p>\n<\/li>\n<li>\n<p> Kafka 2.X + Spark 2.x \u0438\u043b\u0438 Spark 3.x, \u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043d\u0430\u0434\u043e \u0432 RDD-\u043c\u0430\u043d\u0435\u0440\u0435 (\u0447\u0442\u043e \u0434\u043e\u0441\u0442\u043e\u0439\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438);<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0435\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438 \u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441 \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a\u043e\u043c \u043c\u044b \u0441\u043e\u0448\u043b\u0438\u0441\u044c, \u0447\u0442\u043e \u043d\u0430\u0434\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c Spark \u043d\u0435 \u043d\u0438\u0436\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 2.4, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 Structured Streaming \u0438 Kafka. \u0422\u043e \u0435\u0441\u0442\u044c \u0441 Kafka \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u0430\u043a \u0441\u043e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c \u0442\u0438\u043f\u043e\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0438 \u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a\u0430. <\/p>\n<p>\u041f\u0430\u0440\u0443 \u0447\u0430\u0441\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u043e\u0432 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u0434\u0430\u043b\u0438 \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 Kafka \u0447\u0435\u0440\u0435\u0437 Spark \u0435\u0441\u0442\u044c, \u043d\u043e \u043e\u043d\u0430 \u043e\u0447\u0435\u043d\u044c \u0440\u0430\u0437\u0440\u043e\u0437\u043d\u0435\u043d\u043d\u0430. \u0421\u0442\u0430\u043b\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u043c, \u0447\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0451 \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0443\u0436\u0435 \u0431\u044b\u043b\u0430 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0431\u0443\u0434\u0443\u0449\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432 \u0431\u044b\u043b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0434\u0435\u043c\u043e-\u0441\u0442\u0435\u043d\u0434 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432. <\/p>\n<p>\u0418\u0437 \u0434\u0436\u0435\u043d\u0442\u0435\u043b\u044c\u043c\u0435\u043d\u0441\u043a\u0438\u0445 \u0441\u043e\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043c\u0435\u0440\u0447\u0435\u0441\u043a\u043e\u0439 \u0442\u0430\u0439\u043d\u044b \u0438 \u0441\u043f\u0430\u0441\u0435\u043d\u0438\u044f \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f \u043e\u0442 \u043b\u0438\u0448\u043d\u0435\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u2013 \u0441\u0435\u0440\u0432\u0438\u0441 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0440\u0435\u043a\u043b\u0430\u043c\u044b. \u041d\u0430 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 Spark \u044d\u0442\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043e\u0442\u0440\u0430\u0437\u0438\u0442\u0441\u044f \u0438 \u0431\u0443\u0434\u0435\u0442 \u0434\u0430\u0436\u0435 \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u0435\u0439. \u041f\u043e\u043c\u0438\u043c\u043e \u044d\u0442\u043e\u0433\u043e, \u0445\u043e\u0440\u043e\u0448\u0438\u043c\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0433\u0443\u0442 \u0441\u043b\u0443\u0436\u0438\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u0431\u0438\u0440\u0436 (\u043a\u0440\u0438\u043f\u0442\u043e\u0431\u0438\u0440\u0436) \u0438\u043b\u0438 \u0432\u0441\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0434\u0430\u0442\u0447\u0438\u043a\u0438 \u043d\u0430 \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u044f\u0442\u0438\u0438 \u0438 \u0432 \u043e\u0444\u0438\u0441\u0435.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u043d\u0430\u0447\u0430\u043b\u0438 \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u00ab\u043e\u043a\u0435\u0430\u043d\u00bb Big Data-\u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0439, \u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0437\u043d\u0430\u0442\u044c \u2013 \u0447\u0442\u043e \u0438\u0437 \u0441\u0435\u0431\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Kafka, Spark \u0438 \u0447\u0435\u043c \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u044c\u043d\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f Spark Streaming \u0438 Structured Streaming. \u0422\u0435\u0445, \u043a\u043e\u043c\u0443 \u044d\u0442\u0438 \u0441\u043b\u043e\u0432\u0430 \u0443\u0436\u0435 \u0445\u043e\u0440\u043e\u0448\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u044b, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u0435\u0451 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u0440\u0430\u0442\u043a\u043e \u043e Spark<\/summary>\n<div class=\"spoiler__content\">\n<p>Spark \u2013 \u044d\u0442\u043e \u043d\u0430\u0443\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0437\u0430\u0440\u043e\u0434\u0438\u0432\u0448\u0438\u0439\u0441\u044f \u0432 \u043a\u0430\u043b\u0438\u0444\u043e\u0440\u043d\u0438\u0439\u0441\u043a\u043e\u043c \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442\u0435 \u0432 2009 \u0438 \u0441\u0442\u0430\u0432\u0448\u0438\u0439 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445. \u0415\u0433\u043e \u0433\u043b\u0430\u0432\u043d\u044b\u043c \u0430\u0432\u0442\u043e\u0440\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0443\u043c\u044b\u043d\u043e-\u043a\u0430\u043d\u0430\u0434\u0441\u043a\u0438\u0439 \u0443\u0447\u0451\u043d\u044b\u0439 \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u043a\u0438 \u041c\u0430\u0442\u0435\u0439 \u0417\u0430\u0445\u0430\u0440\u0438\u044f (Matei Zaharia).\u00a0Spark \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0431\u044b\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 Scala \u0438 \u0437\u0430\u0442\u0435\u043c \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043d \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Java. \u0414\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0440\u044d\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043a\u0430\u043a \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445, \u0442\u0430\u043a \u0438 \u0441\u043b\u0430\u0431\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u041f\u043e\u043c\u0438\u043c\u043e \u0440\u043e\u0434\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432 Scala, Java, \u0430 \u0442\u0430\u043a\u0436\u0435 R, \u0434\u0430\u043d\u043d\u044b\u0439 \u0444\u0440\u044d\u0439\u043c\u0432\u043e\u0440\u043a \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0438 \u0432 Python-\u0441\u043a\u0440\u0438\u043f\u0442\u0430\u0445. \u00a0<\/p>\n<p>Spark \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c\u0438 \u0438 \u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a\u0430\u043c\u0438: \u0431\u0443\u0434\u044c \u0442\u043e \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 (PostgreSQL, Oracle), NoSQL (Cassandra, MongoDB), \u0444\u0430\u0439\u043b\u044b \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 (csv, json, parquet) \u0438\u043b\u0438 \u0442\u043e\u043f\u0438\u043a\u0438 Kafka. \u0412\u0434\u043e\u0431\u0430\u0432\u043e\u043a \u043a \u044d\u0442\u043e\u043c\u0443 \u0432 Spark \u0435\u0441\u0442\u044c 4 \u043c\u043e\u0434\u0443\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0442 \u0436\u0438\u0437\u043d\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u0430\u0442\u0430-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0443, \u043d\u043e \u0438 \u0434\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0442\u0438\u0441\u0442\u0443:<\/p>\n<ul>\n<li>\n<p>SQL \u2013 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c SQL-\u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430\u0434 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445;<\/p>\n<\/li>\n<li>\n<p>Streaming \u2013 \u043c\u043e\u0434\u0443\u043b\u044c \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0434\u0443\u043b\u044e \u043f\u043e \u0441\u0443\u0442\u0438 \u0438 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u0441\u0442\u0430\u0442\u044c\u044f;<\/p>\n<\/li>\n<li>\n<p>MLlib \u2013 \u043d\u0430\u0431\u043e\u0440 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>GraphX \u2013 \u043c\u043e\u0434\u0443\u043b\u044c \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0433\u0440\u0430\u0444\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0434\u043d\u043e\u0439 \u0438\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0438\u0434\u0435\u043e\u043b\u043e\u0433\u0438\u0439 Spark \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u043e\u0435 \u043f\u043e\u043d\u044f\u0442\u0438\u0435 \u043a\u0430\u043a \u00ab\u043b\u0435\u043d\u0438\u0432\u044b\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f\u00bb (lazy evaluation). \u0422\u043e \u0435\u0441\u0442\u044c \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u0434 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043d\u0430\u0447\u043d\u0443\u0442\u0441\u044f \u043d\u0435 \u0441\u0440\u0430\u0437\u0443, \u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 Spark \u0443\u0432\u0438\u0434\u0438\u0442 \u0432 \u0441\u0432\u043e\u0451\u043c \u043f\u043b\u0430\u043d\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u2013 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0415\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u0435\u0433\u043e \u0438\u0434\u0435\u043e\u043b\u043e\u0433\u0438\u0435\u0439 (\u0438\u043b\u0438 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e) \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u2013 \u043d\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043a \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f\u043c, \u0430 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043a \u0434\u0430\u043d\u043d\u044b\u043c. \u042d\u0442\u043e\u0442 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430 HDFS \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435, \u0433\u0434\u0435 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0444\u0430\u0439\u043b, \u043f\u043e\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0438 \u0440\u0435\u043f\u043b\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u0435\u0439, \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u043d\u043e\u0434\u0430\u0445 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430. Spark \u0441\u0430\u043c \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 (\u0442\u0440\u0430\u043d\u0441\u043b\u0438\u0440\u0443\u0435\u0442) \u043a\u043e\u0434-\u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u043f\u043e \u0432\u0441\u0435\u043c \u0443\u0437\u043b\u0430\u043c \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430, \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u0442 \u0435\u0433\u043e \u043d\u0430 \u043f\u043e\u0434\u0437\u0430\u0434\u0430\u0447\u0438, \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043f\u043b\u0430\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u0412\u0441\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0442 \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438. \u041d\u0438\u0436\u0435 \u2013 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0438\u0447\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u044b \u0440\u0430\u0431\u043e\u0442\u044b Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/24b\/0a6\/3e8\/24b0a63e8ccbc7a8124d5477cce316c2.png\" alt=\"\u0421\u0445\u0435\u043c\u0430 \u0440\u0430\u0431\u043e\u0442\u044b Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \" title=\"\u0421\u0445\u0435\u043c\u0430 \u0440\u0430\u0431\u043e\u0442\u044b Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \" width=\"596\" height=\"320\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/24b\/0a6\/3e8\/24b0a63e8ccbc7a8124d5477cce316c2.png\"\/><figcaption>\u0421\u0445\u0435\u043c\u0430 \u0440\u0430\u0431\u043e\u0442\u044b Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f <\/figcaption><\/figure>\n<p>\u041f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0432\u044b\u043c \u0447\u0435\u0440\u0435\u0437 SparkSession (\u0432 \u0440\u0430\u043d\u043d\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 SparkContext) \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u043e\u0440, \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 Driver, \u043e\u043d \u043e\u0431\u0449\u0430\u0435\u0442\u0441\u044f \u0441\u043e \u0432\u0441\u0435\u043c\u0438 Worker\u2019\u0430\u043c\u0438 (\u0440\u0430\u0431\u043e\u0447\u0438\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430), \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 (RAM \u0438 CPU). \u041a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u0443\u0437\u0435\u043b \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 Executor\u2019\u043e\u0432 (\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0435\u0439), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0437\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 Task\u2019\u0430 (\u0417\u0430\u0434\u0430\u0447\u0438) \u2013 \u043d\u0430\u0438\u043c\u0435\u043d\u044c\u0448\u0430\u044f \u0435\u0434\u0438\u043d\u0438\u0446\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430, \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0435 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u043f\u043e\u0440\u0446\u0438\u0435\u0439 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 \u0440\u0430\u0437\u0434\u0435\u043b\u0443 RDD. \u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 Driver\u2019\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0451 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044f\u0445. RDD (Resilient Distributed Dataset) \u2013 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u044f, \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u0430\u044f, \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u0430\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u0445\u0440\u0430\u043d\u044f\u0449\u0438\u0445\u0441\u044f \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<p>\u041d\u0430\u0434\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e Spark \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043d\u0430 \u043c\u0435\u0441\u0442\u0435 \u2013 \u0435\u0433\u043e \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0430\u044e\u0442 \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u044e\u0442. \u0414\u043e Spark 1.6 \u0431\u044b\u043b \u0442\u043e\u043b\u044c\u043a\u043e RDD API \u0441 \u043d\u0435 \u0441\u0430\u043c\u043e\u0439 \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u043c\u0430\u043d\u0435\u0440\u043e\u0439 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0439, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u2013\u00a0\u0432 \u043c\u0430\u043d\u0435\u0440\u0435 MapReduce. \u041f\u043e\u0442\u043e\u043c \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u0442\u0430\u043a\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043a\u0430\u043a Dataframe \u0438 Dataset, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043a\u0430\u043a c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439, \u0445\u0440\u0430\u043d\u044f\u0449\u0435\u0439\u0441\u044f \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438. \u0422\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0441\u0442\u0430\u043b\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0432 SQL-\u043c\u0430\u043d\u0435\u0440\u0435 (\u0443\u0440\u0430!).\u00a0 <\/p>\n<p>\u0412 Spark 2.0 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f SparkSession, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0442\u0430\u043b \u0435\u0434\u0438\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u0432\u0445\u043e\u0434\u0430 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0438 \u0434\u0430\u043d\u043d\u044b\u0445 Spark. \u0422\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u043e\u043d \u0437\u0430\u043c\u0435\u043d\u0438\u043b \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a SparkContext, SQLContext, HiveContext, SparkConf \u0438 StreamingContext (\u0445\u043e\u0442\u044f \u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442 \u0438\u0445 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c).<\/p>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u0432\u0435\u0440\u0441\u0438\u0438 2.4, Kafka \u0441\u0442\u0430\u043b \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0434\u0443\u043b\u044f Structured Streaming. \u0412 3 \u0432\u0435\u0440\u0441\u0438\u0438 Spark \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0438<br \/>\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438: \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0435\u043d SQL-\u0434\u0432\u0438\u0436\u043e\u043a,<br \/>\u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a Python \u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 PySpark, \u043e\u0431\u0440\u0435\u0437\u043a\u0430 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0445<br \/>\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 \u0438 \u043c\u043d\u043e\u0433\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435. \u041a\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b \u0432\u0441\u0435 \u043d\u043e\u0432\u043e\u0432\u0432\u0435\u0434\u0435\u043d\u0438\u044f Spark 3.0, \u0442\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441\u043e \u0441\u0442\u0430\u0442\u044c\u0451\u0439: <a href=\"https:\/\/databricks.com\/session_na20\/deep-dive-into-the-new-features-of-apache-spark-3-0\">https:\/\/databricks.com\/session_na20\/deep-dive-into-the-new-features-of-apache-spark-3-0<\/a><\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 Spark Structured Streaming<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8dd\/e6e\/8e2\/8dde6e8e29aec9e92fdcd082215526dc.png\" width=\"1299\" height=\"467\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8dd\/e6e\/8e2\/8dde6e8e29aec9e92fdcd082215526dc.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 Structured Streaming \u0431\u044b\u043b\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0432 Spark 2.0 \u0432 2016 \u0433\u043e\u0434\u0443 \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Apache Spark \u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430. \u0421 \u0432\u0435\u0440\u0441\u0438\u0438 Spark 2.2 \u043e\u043d \u0431\u044b\u043b \u043f\u0440\u0438\u0437\u043d\u0430\u043d \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u043c, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 Structured Streaming \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 \u0444\u0440\u0435\u0439\u043c\u043e\u0432\u0440\u043a\u0435 Spark, \u0430 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e DStreams \u2013 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u043c. <\/p>\n<p>Structured Streaming, \u0442\u0430\u043a \u0436\u0435 \u043a\u0430\u043a \u0438 \u0435\u0433\u043e \u043f\u0440\u0435\u0434\u0448\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0438\u043a Spark Streaming, \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u043c\u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445: TCP-\u0441\u043e\u043a\u0435\u0442\u044b, \u0444\u0430\u0439\u043b\u044b (\u0438\u0437 HDFS, S3, \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0424\u0421), Kafka, AWS Kinesis \u0438 \u043f\u043e\u043c\u0438\u043c\u043e \u044d\u0442\u043e\u0433\u043e SQL \u0438 NoSQL \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u043c SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u043d\u0430 \u043c\u043e\u0434\u0443\u043b\u0435 Spark SQL \u0438 API \u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 \u2013 Dataframe \u0438 Dataset, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u043c\u0438 \u0432 \u044f\u0437\u044b\u043a\u0430\u0445 Java, Scala, Python \u0438 R.<\/p>\n<p>\u0423\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u0439 Spark Streaming (\u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 DStream) \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442 RDD API \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e\u0442\u043e\u043a\u0430, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0430\u044f \u0441\u0435\u0440\u0438\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0437\u0430\u0434\u0430\u043d\u0438\u0439 \u043f\u0430\u043a\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 \u0441\u0442\u0438\u043b\u0435 map\/reduce. <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/90d\/dd1\/c06\/90ddd1c06ca394cf5fdbf5aecfa7c33d.png\" alt=\"\u041f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b Spark DStream\" title=\"\u041f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b Spark DStream\" width=\"1200\" height=\"628\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/90d\/dd1\/c06\/90ddd1c06ca394cf5fdbf5aecfa7c33d.png\"\/><figcaption>\u041f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b Spark DStream<\/figcaption><\/figure>\n<p>\u0412 \u043d\u043e\u0432\u043e\u043c Structured Streaming\u2019\u0435 \u0431\u044b\u043b\u043e \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0430 \u0435\u0434\u0438\u043d\u0430\u044f \u0443\u043d\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043f\u0430\u043a\u0435\u0442\u043d\u043e\u0439 \u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u043e\u0442\u043e\u0439\u0434\u044f \u043e\u0442 RDD API. \u041f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0430\u043b \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u0430\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0430.   <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f24\/4e2\/1d5\/f244e21d5dfd0a1543074a46364286ca.png\" alt=\"\u041c\u043e\u0434\u0435\u043b\u044c \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 Structured Streaming \" title=\"\u041c\u043e\u0434\u0435\u043b\u044c \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 Structured Streaming \" width=\"807\" height=\"431\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f24\/4e2\/1d5\/f244e21d5dfd0a1543074a46364286ca.png\"\/><figcaption>\u041c\u043e\u0434\u0435\u043b\u044c \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 Structured Streaming <\/figcaption><\/figure>\n<p>\u0412 Structured Streaming \u0435\u0441\u0442\u044c \u0442\u0440\u0438 \u0440\u0435\u0436\u0438\u043c\u0430 \u0432\u044b\u0432\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p><strong>Append mode<br \/><\/strong>\u0422\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u043a \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0441 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430, \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0432\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435. \u042d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 (\u0432 DataFram\u0435) \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c\u0441\u044f;<\/p>\n<\/li>\n<li>\n<p><strong>Update mode<\/strong><br \/>\u0412\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0431\u0443\u0434\u0443\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u0441\u0442\u0440\u043e\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0441 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430. \u042d\u0442\u043e\u0442 \u0440\u0435\u0436\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0434\u043b\u044f \u043f\u0440\u0438\u0435\u043c\u043d\u0438\u043a\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0438\u0437\u043d\u0443\u0442\u0440\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b PostgreSQL;<\/p>\n<\/li>\n<li>\n<p><strong>Complete mode<\/strong><br \/>\u0412\u0441\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0430\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0430 (DataFrame) \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0432\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u044d\u0442\u043e\u0433\u043e, \u0432 Structured Streaming \u0435\u0441\u0442\u044c \u0434\u0432\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0444\u0438\u0447\u0438 \u2013 window() \u0438 withWatermark(). \u0427\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435:<\/p>\n<ul>\n<li>\n<p><strong>window()<\/strong> \u2013 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u0440\u0430\u0437\u0431\u0438\u0432\u043a\u043e\u0439 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u043e\u043a\u043d\u0430\u043c (\u043e\u0442\u0440\u0435\u0437\u043a\u0430\u043c), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u0430\u0436\u0434\u044b\u0435 30 \u0441\u0435\u043a\u0443\u043d\u0434 \u0438\u043b\u0438 \u043a\u0430\u0436\u0434\u044b\u0435 5 \u043c\u0438\u043d\u0443\u0442. \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u2013 \u043f\u043e \u043a\u0430\u043a\u043e\u043c\u0443 \u043f\u043e\u043b\u044e \u0442\u0438\u043f\u0430 timestamp (\u0434\u0430\u0442\u0430-\u0432\u0440\u0435\u043c\u044f, \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u044b \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e) \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u044e \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0438 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u0435\u043c. \u0412\u0434\u043e\u0431\u0430\u0432\u043e\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0441\u043a\u043e\u043b\u044c\u0436\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u043a\u043d\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 1 \u043c\u0438\u043d\u0443\u0442\u0443. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043a\u0430\u0436\u0434\u0443\u044e 1 \u043c\u0438\u043d\u0443\u0442\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u044e \u0437\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 5 \u043c\u0438\u043d\u0443\u0442;<\/p>\n<\/li>\n<li>\n<p><strong>withWatermark()<\/strong> \u2013 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0438\u043e\u0434\u0430. \u0418\u043d\u044b\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u00ab\u043f\u0440\u043e\u0441\u0440\u043e\u0447\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u00bb \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u043e\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u043d\u0430 \u0447\u0430\u0441\u0430\u0445 12:15, \u0430 \u043c\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 \u043e\u043a\u043d\u043e \u0432 5 \u043c\u0438\u043d\u0443\u0442, \u0442\u0430\u043a\u043e\u0439 \u0436\u0435 \u043f\u0435\u0440\u0438\u043e\u0434 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f, \u0438 \u0432 \u044d\u0442\u0438 12:15 \u043f\u0440\u0438\u0448\u0451\u043b \u043f\u0430\u043a\u0435\u0442 \u0438\u0437 \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e \u0437\u0430 12:03, \u0442\u043e \u0442\u0430\u043a\u0443\u044e \u043f\u043e\u0440\u0446\u0438\u044e \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u044b \u043e\u0442\u0431\u0440\u043e\u0441\u0438\u043c. \u041f\u0440\u0438\u0447\u0451\u043c \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043a\u0430\u043a \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043c\u0435\u0442\u043a\u0435 \u043f\u0440\u0438\u0451\u043c\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u0442\u0430\u043a \u0438 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438\u0445 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u0430 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 (\u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0437\u0430\u0434\u0430\u0447\u0438).<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0432\u0430\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043e\u0434\u0438\u043d \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u2013 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0445 \u0442\u043e\u0447\u0435\u043a (checkpoint). \u0418\u0445 \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0446\u0435\u043b\u044c\u2013 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0445 \u0437\u0430\u0434\u0430\u043d\u0438\u0439. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c, \u0445\u0440\u0430\u043d\u044f\u0449\u0438\u043c\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u0430\u0445 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0445 \u0442\u043e\u0447\u0435\u043a, \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u0431\u043e\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u0438\u043b\u0438 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043e\u0448\u0438\u0431\u043a\u0438. \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u0432 Spark \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0447\u0435\u0442\u044b\u0440\u0435\u0445 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<ul>\n<li>\n<p><strong>source<\/strong> \u2013 \u0444\u0430\u0439\u043b\u044b \u0432 \u044d\u0442\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u0445, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f Apache Kafka \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043a\u0430\u0440\u0442\u0443 \u043c\u0435\u0436\u0434\u0443 \u0440\u0430\u0437\u0434\u0435\u043b\u0430\u043c\u0438 (\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u044f\u043c\u0438) \u0442\u043e\u043f\u0438\u043a\u0430 \u0438 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u043e \u0438 \u043d\u0435 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430;<\/p>\n<\/li>\n<li>\n<p><strong>offsets<\/strong> \u2013 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0444\u0430\u0439\u043b \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u0430. \u041e\u043d \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u0430 \u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043a\u043b\u0430\u0441\u0441\u043e\u043c apache.spark.sql.execution.streaming.OffsetSeqLog. \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u2013 \u044d\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0430 JSON \u0441 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432 \u0438 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u043c \u00abKafka\u00bb \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438\u043c\u044f \u0442\u043e\u043f\u0438\u043a\u0430, \u043d\u043e\u043c\u0435\u0440 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438 \u0438 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u0430: {&#171;some_data&#187;: {&#171;0&#187;: 341}};<\/p>\n<\/li>\n<li>\n<p><strong>commits<\/strong> (\u043a\u043e\u043c\u043c\u0438\u0442\u044b \u0438\u043b\u0438 \u043b\u043e\u0433\u0438 \u0444\u0438\u043a\u0441\u0430\u0446\u0438\u0438) \u2013 \u0444\u0430\u0439\u043b-\u043c\u0430\u0440\u043a\u0435\u0440 \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u0432\u043e\u0434\u044f\u043d\u043e\u043c \u0437\u043d\u0430\u043a\u0435 (watermark), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u0435. \u041e\u043d \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043a\u043b\u0430\u0441\u0441\u043e\u043c apache.spark.sql.execution.streaming.CommitLog, \u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u2013 org.apache.spark.sql.execution.streaming.CommitMetadata. \u0424\u0430\u0439\u043b \u043a\u043e\u043c\u043c\u0438\u0442\u043e\u0432 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0443 \u0437\u0430\u043f\u0438\u0441\u044c \u0441 \u0432\u043e\u0434\u044f\u043d\u044b\u043c \u0437\u043d\u0430\u043a\u043e\u043c, \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u043c \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e \u0437\u0430\u043f\u0440\u043e\u0441\u0430: {\u201cnextBatchWatermarkMs\u201d: 1655500250234};<\/p>\n<\/li>\n<li>\n<p><strong>state<\/strong> (\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435) \u2013 \u043c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438. \u0422\u0430\u043a\u0436\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043b\u043e\u0433\u0438\u043a\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u042d\u0442\u0438 \u0444\u0430\u0439\u043b\u044b \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u0441\u0436\u0430\u0442\u043e\u043c \u0432\u0438\u0434\u0435.<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041a\u0440\u0430\u0442\u043a\u043e \u043e Kafka<\/summary>\n<div class=\"spoiler__content\">\n<p>Apache Kafka \u2013 \u044d\u0442\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 LinkedIn, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043f\u0443\u0449\u0435\u043d\u0430 \u0432 \u0441\u0432\u0435\u0442 \u043f\u043e\u0434 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0435\u0439 Apache \u0432 2012 \u0433\u043e\u0434\u0443.\u00a0\u042d\u0442\u043e \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0439 \u0431\u0440\u043e\u043a\u0435\u0440 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u0442.\u0435. \u0448\u0438\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0441 \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c\u044e, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u043e\u0436\u043d\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u0451 \u0434\u0430\u043d\u043d\u044b\u0435. \u0415\u0441\u043b\u0438 \u043a\u0440\u0430\u0442\u043a\u043e, \u0442\u043e Kafka \u2013 \u044d\u0442\u043e \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u0436\u0443\u0440\u043d\u0430\u043b \u043a\u043e\u043c\u043c\u0438\u0442\u043e\u0432. \u0423 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 API, \u043e\u043d \u043b\u0435\u0433\u043a\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c \u0438 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432. \u0411\u0430\u0437\u043e\u0432\u0430\u044f \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u043b\u043e\u0433\u0438\u044f:<\/p>\n<ul>\n<li>\n<p><strong>producer<\/strong> \u2013 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\/\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439;<\/p>\n<\/li>\n<li>\n<p><strong>consumer<\/strong> \u2013 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\/\u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439;<\/p>\n<\/li>\n<li>\n<p><strong>topic<\/strong> \u2013 \u0442\u0435\u043c\u0430, \u0442.\u0435. \u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 (\u0432 \u0438\u0434\u0435\u0430\u043b\u0435 \u043e\u0434\u043d\u043e\u0440\u043e\u0434\u043d\u044b\u0439) \u043f\u043e\u0442\u043e\u043a \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0441 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435\u043c. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443: \u043d\u0430 \u043a\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u043c \u0442\u0435\u043b\u0435\u0432\u0438\u0434\u0435\u043d\u0438\u0438 \u0435\u0441\u0442\u044c \u043a\u0430\u043d\u0430\u043b \u043f\u0440\u043e \u0440\u044b\u0431\u0430\u043b\u043a\u0443 \u0438, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0432\u0441\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043d\u0430 \u043d\u0451\u043c \u0431\u0443\u0434\u0443\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e \u0440\u044b\u0431\u0430\u043b\u043a\u0443, \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043f\u0440\u043e \u043a\u0443\u043b\u0438\u043d\u0430\u0440\u0438\u044e;<\/p>\n<\/li>\n<li>\n<p><strong>partition<\/strong> \u2013 \u0441\u0435\u043a\u0446\u0438\u044f\/\u0440\u0430\u0437\u0434\u0435\u043b \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0435\u043c\u044b. \u0411\u044b\u0442\u043e\u0432\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440: \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0451\u043c\u0441\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0430, \u043a\u043e\u0433\u0434\u0430 \u0431\u0443\u043c\u0430\u0436\u043d\u044b\u0435 \u0433\u0430\u0437\u0435\u0442\u044b \u0431\u044b\u043b\u0438 \u00a0\u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438. \u041a\u0430\u0436\u0434\u043e\u0435 \u0443\u0442\u0440\u043e \u0443 \u043a\u0438\u043e\u0441\u043a\u0430 (\u0431\u0440\u043e\u043a\u0435\u0440\u0430) \u0432\u044b\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u0438\u043d\u043d\u0430\u044f \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0447\u0442\u043e\u0431\u044b \u043a\u0443\u043f\u0438\u0442\u044c \u043e\u0434\u043d\u0443 \u0438 \u0442\u0443\u0436\u0435 \u0444\u0438\u043d\u0430\u043d\u0441\u043e\u0432\u0443\u044e (\u0442\u043e\u043f\u0438\u043a) \u0433\u0430\u0437\u0435\u0442\u0443 (\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435), \u0438 \u0434\u0430\u043b\u0435\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u0443\u0436\u0435 \u0447\u0438\u0442\u0430\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0443\u044e \u0435\u043c\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e (\u043f\u043e\u043b\u0435 \u0438\u0437 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f). \u041e\u0447\u0435\u0440\u0435\u0434\u044c \u0433\u0443\u0434\u0438\u0442 \u0438\u0437-\u0437\u0430 \u043d\u0435\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0430 \u0434\u043e\u043b\u0433\u0438\u043c \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435\u043c, \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043f\u0430\u0437\u0434\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0443. \u041e\u0434\u043d\u0430\u0436\u0434\u044b \u0441\u0442\u0430\u0432\u044f\u0442 \u0435\u0449\u0451 \u0434\u0432\u0430 \u043a\u0438\u043e\u0441\u043a\u0430 (\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438), \u043f\u0440\u043e\u0434\u0430\u044e\u0449\u0438\u0435 \u0442\u0430\u043a\u0438\u0435 \u0436\u0435 \u0433\u0430\u0437\u0435\u0442\u044b \u2013 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f;<\/p>\n<\/li>\n<li>\n<p><strong>offset<\/strong> \u2013 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435.\u00a0 \u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e \u2013 \u044d\u0442\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u043e\u0432\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u043e\u043f\u0438\u043a\u0430 (\u0442\u0435\u043c\u044b).<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2ee\/a69\/a09\/2eea69a09bced14f02be7204941d68c3.png\" alt=\"\u041c\u043e\u0434\u0435\u043b\u044c \u0440\u0430\u0431\u043e\u0442\u044b Kafka \" title=\"\u041c\u043e\u0434\u0435\u043b\u044c \u0440\u0430\u0431\u043e\u0442\u044b Kafka \" width=\"678\" height=\"523\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2ee\/a69\/a09\/2eea69a09bced14f02be7204941d68c3.png\"\/><figcaption>\u041c\u043e\u0434\u0435\u043b\u044c \u0440\u0430\u0431\u043e\u0442\u044b Kafka <\/figcaption><\/figure>\n<p>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 (producer&#8217;\u044b) \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 Kafka \u0438 \u0434\u0430\u043b\u0435\u0435 \u043e\u043d\u0438 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438, \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f\u043c\u0438. \u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u0442\u043e\u043f\u0438\u043a\u0435, a \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043d\u0435\u0433\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u0422\u043e\u043f\u0438\u043a\u0438 (\u0442\u0435\u043c\u044b) \u043c\u043e\u0433\u0443\u0442 \u00ab\u0440\u0430\u0437\u0434\u0443\u0432\u0430\u0442\u044c\u0441\u044f\u00bb \u0438\u0437-\u0437\u0430 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0449\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u00a0\u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0434\u0435\u043b\u0438\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u0442\u043e\u043f\u0438\u043a\u0438 \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043c\u0435\u043b\u043a\u0438\u0435 \u0441\u0435\u043a\u0446\u0438\u0438 (partitions) \u0434\u043b\u044f \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u0438. <\/p>\n<p>Kafka \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442, \u0447\u0442\u043e \u0432\u0441\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438 \u0431\u0443\u0434\u0443\u0442 \u0443\u043f\u043e\u0440\u044f\u0434\u043e\u0447\u0435\u043d\u044b \u0432 \u0442\u043e\u0439 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b\u0438. \u0412\u0430\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e Kafka \u043d\u0435 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0435\u043c \u0438 \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0443\u0434\u0430\u043b\u044f\u044e\u0442\u0441\u044f, \u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u0445\u0440\u0430\u043d\u0438\u0442 \u0438\u0445 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0438\u043e\u0434\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 (\u0432 \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445, \u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438 \u0446\u0435\u043b\u044b\u0435 \u0441\u0443\u0442\u043a\u0438), \u043b\u0438\u0431\u043e \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u0435\u043b.<\/p>\n<p>\u041d\u0430\u043f\u043e\u0441\u043b\u0435\u0434\u043e\u043a \u0441\u0442\u043e\u0438\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c, \u0447\u0442\u043e Kafka \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 Zookeeper \u2013 \u0441\u043b\u0443\u0436\u0431\u043e\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438, \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0438, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. Kafka \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442 ZooKeeper \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u043e \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u044f\u0445 \u0441\u0432\u043e\u0438\u0445 \u0442\u043e\u043f\u0438\u043a\u043e\u0432 \u0438 \u0431\u0440\u043e\u043a\u0435\u0440\u0430\u0445, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u0431\u0440\u043e\u043a\u0435\u0440\u0430 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430. \u0412 \u0432\u0435\u0440\u0441\u0438\u0438 Kafka 2.8.0 \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u0435\u0437 Zookeeper: <a href=\"https:\/\/itchef.ru\/articles\/60157\/\">https:\/\/itchef.ru\/articles\/60157\/<\/a><\/p>\n<\/div>\n<\/details>\n<h2>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u00ab\u0420\u0435\u043a\u043b\u0430\u043c\u043d\u0430\u044f \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430\u00bb<\/h2>\n<p>\u0418\u0434\u0435\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0432\u043f\u043e\u043b\u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u0430\u044f. \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0430\u0433\u0435\u043d\u0442\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u0442 \u0440\u0435\u043a\u043b\u0430\u043c\u0443 \u043d\u0430 \u0441\u0430\u0439\u0442\u0430\u0445 \u0438 \u0432 \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0442\u044f\u0445. \u0420\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u043f\u0438\u0448\u0443\u0442 \u0432 \u0442\u043e\u043f\u0438\u043a\u0438 Kafka \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430\u0445 \u0438 \u043a\u043b\u0438\u043a\u0430\u0445. \u0414\u0430\u043b\u0435\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 PySpark Structured Streaming \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0432\u0441\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438 \u00a0\u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\/\u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u0435\u0442\/\u0444\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u0442\/ \u043e\u0431\u043e\u0433\u0430\u0449\u0430\u0435\u0442 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a\u0438.<\/p>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u044b:<\/p>\n<ul>\n<li>\n<p>Ubuntu;<\/p>\n<\/li>\n<li>\n<p>Java X;<\/p>\n<\/li>\n<li>\n<p>Scala X;<\/p>\n<\/li>\n<li>\n<p>Kafka 2.12;<\/p>\n<\/li>\n<li>\n<p>Spark 2.4 \/ 3.1.1;<\/p>\n<\/li>\n<li>\n<p>Python 3.X;<\/p>\n<\/li>\n<li>\n<p>Jupyter notebook (\u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e).<\/p>\n<\/li>\n<\/ul>\n<p>\u042d\u0442\u043e \u043a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043d\u0435\u0439 \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u043e \u0443 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0432 \u0432\u0438\u0434\u0443 \u0438\u0445 \u0432\u0430\u0440\u0438\u0430\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u0438. <\/p>\n<p>\u041c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u0442\u043e\u043a Kafka \u00abadViews\u00bb (\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a) \u2013 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u044b \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u043e\u0432 (\u043d\u0430 \u0441\u0430\u0439\u0442\u0430\u0445 \u0438 \u0432 \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0442\u044f\u0445);<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0442\u043e\u043a Kafka \u00abadClicks\u00bb (\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a) \u2013 \u043a\u043b\u0438\u043a\u0438 \u043f\u043e \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u043c \u0431\u043b\u043e\u043a\u0430\u043c;<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 PySpark \u2013 ETL-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440;<\/p>\n<\/li>\n<li>\n<p>\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u0424\u0421 \u2013 \u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a \u0434\u0430\u043d\u043d\u044b\u0445 (json-\u0444\u0430\u0439\u043b\u044b);<\/p>\n<\/li>\n<li>\n<p>\u0422\u0430\u0431\u043b\u0438\u0446\u0430 PostgreSQL;<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0442\u043e\u043a Kafka \u00abadDescription\u00bb (\u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a\/\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a) \u2013 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u0430\u0445;<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0442\u043e\u043a Kafka \u00abadStatistic\u00bb (\u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a\/\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a) \u2013 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u0445 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f\u0445.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1ec\/111\/fac\/1ec111fac39c50acc0b8dc39f2b8f631.png\" alt=\"\u041c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445\" title=\"\u041c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445\" width=\"1111\" height=\"473\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1ec\/111\/fac\/1ec111fac39c50acc0b8dc39f2b8f631.png\"\/><figcaption>\u041c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445<\/figcaption><\/figure>\n<p>\u0414\u0430\u043d\u043d\u044b\u0435 \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0442\u043e\u043f\u0438\u043a\u0438 Kafka \u0431\u0443\u0434\u0443\u0442 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u043d\u0430 Python, \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u0443\u044f \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u043e\u0432. \u042f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0443 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432 Jupyter notebook, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0434\u043e\u0431\u0435\u043d \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u0438 \u043d\u0435\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043d \u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u0432\u0430\u043c \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u0435\u0435 \u2013 \u00a0PyCharm, \u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0438\u043b\u0438 \u043f\u043e \u00ab\u0442\u0440\u0443\u0430\u0439\u0442\u0438\u0448\u043d\u043e\u043c\u0443\u00bb \u2013 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0432\u0441\u0451 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438. <\/p>\n<p>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u044b:<\/p>\n<ol>\n<li>\n<p>Py-\u0441\u043a\u0440\u0438\u043f\u0442 \u00ab<a href=\"http:\/\/producerAdViews.py\">producerAdViews.py<\/a>\u00bb \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0442\u043e\u043f\u0438\u043a Kafka \u00abadViews\u00bb;<\/p>\n<\/li>\n<li>\n<p>Py-\u0441\u043a\u0440\u0438\u043f\u0442 \u00ab<a href=\"http:\/\/producerAdViewsAndClicks.py\">producerAdViewsAndClicks.py<\/a>\u00bb \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0442\u043e\u043f\u0438\u043a\u0438 Kafka \u00abadViews\u00bb  \u0438 \u00abadClicks\u00bb;<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 PySpark \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 Kafka, \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0438\u0445 \u0438 \u0434\u0430\u043b\u0435\u0435:<\/p>\n<ol>\n<li>\n<p>\u0412\u044b\u0432\u043e\u0434\u0438\u0442 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c;<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u0424\u0421 json-\u0444\u0430\u0439\u043b\u044b;<\/p>\n<\/li>\n<li>\n<p> \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0431\u043e\u0433\u0430\u0449\u0451\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0442\u043e\u043f\u0438\u043a Kafka \u00abadDescription\u00bb;<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0440\u0446\u0438\u0439 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0432 pg-\u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u00abad_country_aggregations\u00bb;<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0442\u043e\u043f\u0438\u043a Kafka \u00abadStatistic\u00bb \u2013 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u0445 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f\u0445.<\/p>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432\u0441\u0451 \u044d\u0442\u043e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/h2>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0432\u0441\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u2013 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0438 \u043d\u0435 \u0441\u0430\u043c\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439, \u043d\u043e \u0442\u043e\u0447\u043d\u043e \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u044b\u0439 \u044d\u0442\u0430\u043f. \u0418\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u043d\u0451\u043c \u0438 \u0431\u044b\u043b\u043e \u043d\u0430\u0431\u0438\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0448\u0438\u0448\u0435\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u043a\u0430\u0447\u0430\u043b\u0438 \u043d\u0430\u0432\u044b\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Linux\u2019\u0430\u043c\u0438. \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u044d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0438 \u0432\u0430\u043c \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u0438 \u0442\u0430\u043a \u0436\u0435 \u043f\u0440\u043e\u043a\u0430\u0447\u0430\u0442\u044c\u0441\u044f.<\/p>\n<p><strong>\u042d\u0442\u0430\u043f 1 \u2013 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 PySpark<\/strong><\/p>\n<p>\u0421\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0441\u0432\u0435\u0436\u0443\u044e \u0438 \u0447\u0438\u0441\u0442\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e Ubuntu (20-\u0430\u044f \u0432 \u043c\u043e\u0451\u043c \u0441\u043b\u0443\u0447\u0430\u0435) \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b c PySpark <u>\u0442\u0435\u0445 \u0432\u0435\u0440\u0441\u0438\u0439, \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0442\u0441\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e<\/u>.<\/p>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b:<\/p>\n<ul>\n<li>\n<p>Java 11 (OpenJDK &#171;11.0.15&#187;);<\/p>\n<\/li>\n<li>\n<p>Scala 2.11.12;<\/p>\n<\/li>\n<li>\n<p> Python 3.8;<\/p>\n<\/li>\n<li>\n<p> Spark 3.1.1 \u0434\u043b\u044f Hadoop 3.2 (spark-3.1.1-bin-hadoop3.2);<\/p>\n<\/li>\n<li>\n<p>Jupyter notebook (6.3.0).<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0435\u0440\u0435\u0447\u0435\u043d\u044c \u043a\u043e\u043c\u0430\u043d\u0434 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u044d\u0442\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432:<\/p>\n<details class=\"spoiler\">\n<summary>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 Ubuntu<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"bash\">sudo apt install python3-pip  pip3 install jupyter  jupyter notebook  [shutdown]  sudo apt-get update  sudo apt-get install default-jre  java -version  sudo apt-get install scala  scala -version  pip3 install py4j  >>sudo apt-get install default-jre \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 Home  >> \u0441\u043a\u0430\u0447\u0430\u0442\u044c spark-3.1.1-bin-hadoop3.2.tgz >> \u0440\u0430\u0437\u043e\u0440\u0445\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c sudo tar -zxvf spark-3.1.1-bin-hadoop3.2.tgz  export SPARK_HOME='\/home\/andrey\/spark-3.1.1-bin-hadoop3.2'  export PATH=$SPARK_HOME\/bin:$PATH  export PYTHONPATH=$SPARK_HOME\/python:$PYTHONPATH  nano ~\/.bashrc [copy all comands creating os variables] [# - optional]  sudo chmod 777 spark-3.1.1-bin-hadoop3.2 sudo chmod -R 777 spark-3.1.1-bin-hadoop3.2  cd spark-3.1.1-bin-hadoop3.2  cd python  python3  >>> import pyspark >>> quit()  cd spark-3.1.1-bin-hadoop3.2 sudo chmod 777 python  cd python sudo chmod 777 pyspark <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c Jupyter notebook \u0447\u0435\u0440\u0435\u0437 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0443 PySpark.<\/p>\n<p>\u041f\u0438\u0448\u0435\u043c \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435:<\/p>\n<pre><code class=\"bash\">jupyter notebook<\/code><\/pre>\n<p>\u0412 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u043e\u0442\u043a\u0440\u044b\u0442\u044c\u0441\u044f \u043f\u043e\u0445\u043e\u0436\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u2013 \u044d\u0442\u043e \u0438 \u0431\u0443\u0434\u0435\u0442 \u0441\u0440\u0435\u0434\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f68\/ac2\/f7d\/f68ac2f7d9e897a4cbb6e4004020cc0a.png\" width=\"817\" height=\"330\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f68\/ac2\/f7d\/f68ac2f7d9e897a4cbb6e4004020cc0a.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c\u0438 \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0438\u0437 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u044c PySpark \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0443\u0442\u0438\u043b\u0438\u0442\u044b \u00abfindspark\u00bb. \u0414\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0434\u0430\u0442\u0430\u0444\u0440\u044d\u0439\u043c \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0435\u0433\u043e \u0432 csv-\u0444\u043e\u0440\u043c\u0430\u0442\u0435.<\/p>\n<pre><code class=\"python\">import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  import pyspark from pyspark.sql import SparkSession   print(\"&lt;&lt;---***--- START ---***--->>\")  spark = (SparkSession  .builder  .appName('pyspark_example')  .getOrCreate())   rows = [ (1,\"clothes\"), (2,\"games\"), (3,\"electronics\"), (4,\"cars\"), (5,\"travel\"), (6,\"books\") ]  schema = \"ad_id BIGINT, category STRING\" adCategoryDF = spark.createDataFrame(rows, schema) adCategoryDF.show()  adCategoryDF.repartition(1).write \\             .format(\"csv\") \\             .mode(\"overwrite\") \\             .option(\"header\", \"true\") \\             .option(\"sep\", \"\\t\") \\             .save(\".\/files\/test\")              print(\"&lt;&lt;---***--- END ---***--->>\")<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c33\/30f\/119\/c3330f11928afe34982be9ef53832b31.png\" width=\"600\" height=\"184\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c33\/30f\/119\/c3330f11928afe34982be9ef53832b31.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0423\u0431\u0435\u0434\u0438\u043b\u0438\u0441\u044c, \u0447\u0442\u043e Spark \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0438\u0434\u0451\u043c \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c Kafka.<\/p>\n<p><strong>\u042d\u0442\u0430\u043f 2 \u2013 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 Kafka<\/strong><\/p>\n<p>\u041d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u0432\u0435\u0440\u0441\u0438\u0435\u0439 Kafka, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u044b\u043b\u0430 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u0430 \u0438 \u043d\u0430\u0448\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0435\u0439 \u0434\u043e\u0432\u0435\u0440\u044f\u043b\u0430, \u0431\u044b\u043b\u0430 \u00ab2.12\u00bb, \u0430 \u0435\u0441\u043b\u0438 \u0442\u043e\u0447\u043d\u043e \u2013 kafka_2.12-3.0.0. \u0425\u043e\u0442\u044c \u0432 \u0432\u0435\u0440\u0441\u0438\u0438 Kafka 2.8.0 \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u0435\u0437 Zookeeper, \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430, \u0442\u0430\u043a \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e \u0441\u0442\u0430\u0440\u0438\u043d\u043a\u0435, \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c Zookeeper.<\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Kafka:<\/p>\n<details class=\"spoiler\">\n<summary>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Kafka \u0432 Ubuntu<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"bash\">#download package information from all configured sources sudo apt-get update  #install java sudo apt-get install default-jre java -version  #download binary file wget -P kafka_distr\/ \"https:\/\/dlcdn.apache.org\/kafka\/3.0.0\/kafka_2.12-3.0.0.tgz\"  #extract file tar -xvzf kafka_distr\/kafka_2.12-3.0.0.tgz  #create link on path with kafka ln -s kafka_distr\/kafka_2.12-3.0.0.tgz kafka  #edit config via~\/kafka\/config\/server.propeties delete.topic.enable = true<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041a\u043e\u0433\u0434\u0430 Kafka \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u2013 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u0434\u0438\u043d \u0442\u043e\u043f\u0438\u043a \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043d\u0435\u0433\u043e \u043f\u0430\u0440\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439.<\/p>\n<p>\u0421\u0442\u0430\u0440\u0442\u0443\u0435\u043c Zookeeper:<\/p>\n<pre><code class=\"bash\">cd ~\/kafka bin\/zookeeper-server-start.sh config\/zookeeper.properties<\/code><\/pre>\n<p>\u0421\u0442\u0430\u0440\u0442\u0443\u0435\u043c Kafka:<\/p>\n<pre><code class=\"bash\">bin\/kafka-server-start.sh config\/server.properties<\/code><\/pre>\n<p>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0442\u043e\u043f\u0438\u043a \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\">bin\/kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 2 --topic testTopic<\/code><\/pre>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\">bin\/kafka-console-producer.sh --topic testTopic --bootstrap-server localhost:9092 > message_1 > message_2<\/code><\/pre>\n<p>\u0427\u0438\u0442\u0430\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f (\u0432 \u043d\u043e\u0432\u043e\u043c \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435):<\/p>\n<pre><code class=\"bash\">bin\/kafka-console-consumer.sh --topic testTopic --from-beginning --bootstrap-server localhost:9092 <\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1b5\/f7a\/750\/1b5f7a75005ef138657b3d3aeb5d1b99.png\" width=\"613\" height=\"78\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1b5\/f7a\/750\/1b5f7a75005ef138657b3d3aeb5d1b99.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0423\u0431\u0435\u0434\u0438\u043b\u0438\u0441\u044c, \u0447\u0442\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0438 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u2013 \u0437\u043d\u0430\u0447\u0438\u0442, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u043e\u0442\u043b\u0430\u0434\u043a\u0435 \u0447\u0442\u0435\u043d\u0438\u044f \u0438\u0437 Kafka \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e PySpark, \u0433\u0434\u0435 \u043d\u0430\u0441 \u0438 \u043f\u043e\u0434\u0436\u0438\u0434\u0430\u044e\u0442 \u0441\u044e\u0440\u043f\u0440\u0438\u0437\u044b.<\/p>\n<p><strong>\u042d\u0442\u0430\u043f 3 \u2013 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 PostgreSQL<\/strong><\/p>\n<p>\u0421 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u043e\u0439 PostgresSQL \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043d\u044e\u0430\u043d\u0441\u043e\u0432 \u043d\u0435\u0442 \u2013 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0442\u0430\u0432\u0438\u043c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u00abdeveloper\u00bb. \u0421 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0443\u0434\u0435\u043c \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c\u0441\u044f jdbc-\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432 Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. \u0422\u0430\u043a\u0436\u0435 \u0441\u0440\u0430\u0437\u0443 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u00abad_country_aggregations\u00bb \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0440\u0446\u0438\u0439 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<details class=\"spoiler\">\n<summary>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 PostgreSQL \u0432 Ubuntu<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"bash\">sudo apt update sudo apt install postgresql postgresql-contrib  #create new role sudo -u postgres createuser --interactive >> Output Enter name of role to add: developer Shall the new role be a superuser? (y\/n) y &lt;&lt;  #create db sudo -u postgres createdb advertising  #add pg-user to Ubuntu sudo adduser developer >>  enter password: 123456 Retype new password: Full name []: developer Room Number []: 1 Work Phone []: 1 Home Phone []: 1 Other []: 1 Is the information correct? [Y\/n] Y &lt;&lt;   #change password in PostgreSQL for users: postgres and developer sudo -i -u postgres psql ALTER USER postgres PASSWORD 'xxxxxxx'; ALTER USER developer PASSWORD 'xxxxxxx';  >>quite  #connect to db  sudo -i -u developer psql -U developer -d advertising  CREATE TABLE ad_country_aggregations ( row_timestampTIMESTAMPdefault current_timestamp, row_idSERIAL PRIMARY KEY, country VARCHAR(50), countINT, minINT, maxINT, sumINT, avgDOUBLE PRECISION, time_intervalVARCHAR(50) );  <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p><strong>\u042d\u0442\u0430\u043f 4 \u2013 \u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f PySpark \u0438 Kafka<\/strong><\/p>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0440\u0430\u043d\u0435\u0435 \u0431\u044b\u043b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d Spark \u0432\u0435\u0440\u0441\u0438\u0438 3.1.1, \u0442\u043e \u0432 \u043d\u0451\u043c \u0443\u0436\u0435 \u0434\u0430\u0432\u043d\u043e \u0435\u0441\u0442\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 Structured Streamig \u2013 \u0437\u043d\u0430\u0447\u0438\u0442 \u043c\u043e\u0436\u043d\u043e \u0441\u043c\u0435\u043b\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0433\u043e. \u0414\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u043f\u0440\u043e\u0447\u0442\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0442\u043e\u0433\u043e \u0436\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0442\u043e\u043f\u0438\u043a\u0430 \u00abtestTopic\u00bb. \u041e\u0434\u043d\u043e \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043f\u043e Spark 3.1.1 \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u043e\u0434\u0441\u043a\u0430\u0436\u0435\u0442 \u043a\u0430\u043a \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0435\u0433\u043e \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c. \u0412 \u0441\u043a\u0440\u0438\u043f\u0442\u0435 \u0432\u0441\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0432 \u0442\u043e\u043f\u0438\u043a, \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c.<\/p>\n<p>\u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 \u0447\u0442\u0435\u043d\u0438\u044f \u0438\u0437 Kafka:<\/p>\n<pre><code class=\"python\">checkpoint_path = \".\/checkpoint\/test_1\" kafka_servers = \"localhost:9092\" topic = \"testTopic\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_test_1\")           .getOrCreate())  adViewsDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"earliest\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   query = adViewsDF.writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0432 \u0441\u043a\u0440\u0438\u043f\u0442, \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443, \u0447\u0442\u043e Spark \u043d\u0435 \u0441\u043c\u043e\u0433 \u043d\u0430\u0439\u0442\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0430\u043a\u0438\u043c \u0442\u0438\u043f\u043e\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u043a\u0430\u043a \u00abKafka\u00bb.<\/p>\n<p><code>AnalysisException: Failed to find data source: kafka. Please deploy the application as per the deployment section of \"Structured Streaming + Kafka Integration Guide\".<\/code><\/p>\n<p>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043d\u0435 \u0441\u0442\u0440\u0430\u0448\u043d\u0430\u044f \u0438 \u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435\u0439 \u043f\u043e\u0438\u0441\u043a\u0430. \u041d\u0430\u0445\u043e\u0434\u0438\u043c, \u0447\u0442\u043e \u0432 PySpark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043d\u0430\u0434\u043e \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u043b\u044f \u043a\u0430\u043a\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 Spark \u043a\u0430\u043a\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e Kafka \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. \u0414\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u0432 \u043f\u0430\u0440\u0443 \u0441\u0442\u0440\u043e\u043a:<\/p>\n<pre><code class=\"python\">import os os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'<\/code><\/pre>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0438 \u0432\u043d\u043e\u0432\u044c \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u043c\u0441\u044f \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439:<\/p>\n<p><code>java.lang.IllegalArgumentException: Unsupported class file major version 55<br \/>pyspark.sql.utils.StreamingQueryException: 'Unsupported class file major version 55<\/code><\/p>\n<p>\u041d\u0435\u0434\u043e\u043b\u0433\u0438\u0435 \u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0432 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u0438\u043a\u0435 \u043d\u0430\u0432\u043e\u0434\u044f\u0442 \u043d\u0430 \u043c\u044b\u0441\u043b\u044c, \u0447\u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c Java 8, \u0442\u0430\u043a \u043a\u0430\u043a \u0441 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 Java 11-\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u044e\u0440\u043f\u0440\u0438\u0437\u044b \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438.<\/p>\n<p>\u0427\u0442\u043e \u0436, \u0437\u043d\u0430\u0447\u0438\u0442, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c Java 8 \u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0435\u0451 \u043a\u0430\u043a \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e (11-\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e). \u0421\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0432 Ubuntu \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438, \u043d\u043e \u043c\u043d\u0435 \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u043b\u0441\u044f \u0432\u043e\u0442 \u044d\u0442\u043e\u0442, \u043a\u0430\u043a \u0441\u0430\u043c\u044b\u0439 \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u0438 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0439:<\/p>\n<p>\u0421\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u043c Java 8, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e java-8-openjdk-amd64 (1.8.0_312)<\/p>\n<pre><code class=\"bash\">sudo apt -y install openjdk-8-jre<\/code><\/pre>\n<p>\u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c Java 8, \u043a\u0430\u043a \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e.<\/p>\n<pre><code class=\"bash\">sudo update-alternatives --config java # \u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c &lt;enter> \u0447\u0442\u043e \u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0432\u044b\u0431\u043e\u0440 [*], \u0438\u043b\u0438 \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u043e\u043c\u0435\u0440 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430:  >> \u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c usr\/lib\/jvm\/java-8-openjdk-amd64\/jre\/bin\/java >> Done<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3c8\/740\/b59\/3c8740b597d5c739d3a2e8551831f33c.png\" width=\"653\" height=\"162\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3c8\/740\/b59\/3c8740b597d5c739d3a2e8551831f33c.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u044e Java.<\/p>\n<pre><code class=\"bash\">java -version<\/code><\/pre>\n<p>\u0421\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bcd\/14e\/b40\/bcd14eb40049039dcd2971a2e0a7c46b.png\" width=\"578\" height=\"65\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/bcd\/14e\/b40\/bcd14eb40049039dcd2971a2e0a7c46b.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u043d\u043e\u0432\u044c \u043f\u043e\u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0414\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0447\u0435\u0440\u0435\u0437 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432 \u0442\u043e\u043f\u0438\u043a \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u2013 \u043e\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u0414\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0439 \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 \u0447\u0442\u0435\u043d\u0438\u044f \u0438\u0437 Kafka <\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/test_1\" kafka_servers = \"localhost:9092\" topic = \"testTopic\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_test_1\")           .getOrCreate())  adViewsDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"earliest\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   query = adViewsDF.writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0449\u0451 \u043e\u0434\u043d\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 Kafka<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3cb\/607\/e40\/3cb607e4097035a519d0eb8b3f83592e.png\" width=\"602\" height=\"73\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3cb\/607\/e40\/3cb607e4097035a519d0eb8b3f83592e.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u0438\u0451\u043c \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 PySpark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f2f\/ad0\/991\/f2fad09914e1a5898cbc9dd91949d9ba.png\" width=\"600\" height=\"122\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f2f\/ad0\/991\/f2fad09914e1a5898cbc9dd91949d9ba.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0441\u0440\u0435\u0434\u044b \u043c\u043e\u0436\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u043e\u0439 \u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043a \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0447\u0442\u0435\u043d\u0438\u044f \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0438\u0437 Kafka.<\/p>\n<p>\u041d\u043e \u0435\u0441\u043b\u0438 \u0432\u0434\u0440\u0443\u0433 \u0438\u043d\u0442\u0435\u0440\u0435\u0441 \u0438\u043b\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u043d\u0430\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0432\u044b\u043d\u0443\u0434\u0438\u043b\u0430 \u0432\u0430\u0441 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c Spark 2.4, \u0442\u043e \u043d\u0438\u0436\u0435, \u0432 \u0441\u0432\u0451\u0440\u043d\u0443\u0442\u043e\u043c \u0431\u043b\u043e\u043a\u0435, \u0432\u044b \u0443\u0437\u043d\u0430\u0435\u0442\u0435 \u043a\u0430\u043a\u043e\u0439 \u0435\u0449\u0451 \u043d\u044e\u0430\u043d\u0441 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0432\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0436\u0434\u0430\u0442\u044c.<\/p>\n<details class=\"spoiler\">\n<summary>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f Spark 2.4<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u043b\u0443\u0447\u0430\u0439, \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c Spark \u043d\u0438\u0436\u0435 3 \u0432\u0435\u0440\u0441\u0438\u0438, \u043d\u043e \u0432\u044b\u0448\u0435 2.3 (\u0435\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0432\u0435\u0440\u0441\u0438\u044e \u0435\u0449\u0451 \u043d\u0438\u0436\u0435, \u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u0435 \u043d\u0435 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043d\u0430\u0432\u044b\u043a\u0438, \u0430 \u0434\u0438\u043f\u043b\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438 \u0443\u0431\u0435\u0434\u0438\u0442\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u0441\u0432\u0435\u0436\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e). \u0418\u043c\u0435\u043d\u043d\u043e \u0441 \u0432\u0435\u0440\u0441\u0438\u0438 2.4 Kafka \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043a\u0430\u043a \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0442\u0438\u043f \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0438 \u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a\u0430. \u0414\u0435\u0440\u0436\u0438\u043c \u044d\u0442\u043e \u0432 \u0443\u043c\u0435 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 PySpark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0438\u0437 \u0432\u044b\u0448\u0435 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 (\u043d\u043e \u0441 py-\u043c\u043e\u0434\u0443\u043b\u0435\u043c KafkaUtils). <\/p>\n<p><strong><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<\/em><\/strong><\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432 Jupyter notebook \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e Spark 2.4, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 jar-\u043d\u0438\u043a \u00abspark-2.4.4-bin-hadoop2.7.tgz\u00bb \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<p>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0438\u0437 Kafka:<\/p>\n<pre><code class=\"python\">import findspark findspark.init('\/home\/andrey\/spark-2.4.4-bin-hadoop2.7')  from pyspark.sql import SparkSession from pyspark.streaming.kafka import KafkaUtils   checkpoint_path = \".\/checkpoint\/test_2\" kafka_servers = \"localhost:9092\" topic = \"testTopic\"  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_test_2\")         .getOrCreate())  adViewsDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"earliest\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   query = adViewsDF.writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443:<\/p>\n<p><code>TypeError: an integer is required (got type bytes)<\/code>   <\/p>\n<p>\u0418\u0437 \u0442\u043e\u043f\u0438\u043a\u043e\u0432 \u043d\u0430 \u0444\u043e\u0440\u0443\u043c\u0430\u0445 \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u043c, \u0447\u0442\u043e \u043e\u0448\u0438\u0431\u043a\u0430 \u043d\u0430\u043c\u0435\u043a\u0430\u0435\u0442 \u043d\u0430 \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u0438 Python 3.8 (\u0438 3.9) \u0434\u043b\u044f PySpark 2.4. \u041d\u0430\u0434\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c Python 3.7 \u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0435\u0433\u043e \u043a\u0430\u043a \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e.<\/p>\n<p>\u0421\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c Python 3.7.<\/p>\n<pre><code class=\"bash\">sudo apt update sudo apt install python3.7<\/code><\/pre>\n<p>\u041c\u0435\u043d\u044f\u0435\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e Python:<\/p>\n<p>\u0421\u043f\u043e\u0441\u043e\u0431 1<\/p>\n<pre><code class=\"bash\">nano ~\/.bashrc >> [write OS variable] alias python=\/usr\/bin\/python3.7<\/code><\/pre>\n<p>\u0421\u043f\u043e\u0441\u043e\u0431 2<\/p>\n<pre><code class=\"bash\">sudo update-alternative --install usr\/bin\/python python usr\/bin\/python3.7 1 sudo update-alternative --install usr\/bin\/python python usr\/bin\/python3.8 2<\/code><\/pre>\n<p>\u041d\u043e \u0443\u0432\u044b, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 Jupyter\u2019\u043e\u043c \u044d\u0442\u043e\u0433\u043e \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043c\u0430\u043b\u043e. \u0412 \u043d\u0451\u043c \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u043b\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432\u0435\u0440\u0441\u0438\u044f Python 3.8 \u0438 \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0435\u0451 \u2013 \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430. \u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u043e\u0434\u0443\u043b\u0435\u043c venv (\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u043b\u0438 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435), \u043d\u043e \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0442\u0440\u0435\u043d\u0438\u0440\u043e\u0432\u043e\u043a \u0432 Jupyter\u2019\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0431\u0435\u0433\u043d\u0443\u0442\u044c \u043a \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u043c\u0443 \u0441\u043f\u043e\u0441\u043e\u0431\u0443. \u041f\u043e\u043c\u0438\u043c\u043e \u044d\u0442\u043e\u0433\u043e, \u043c\u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0431\u043e\u0440 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0434\u043b\u044f Python 3.7 \u0438\u0437 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 Python 3.8:<\/p>\n<pre><code class=\"bash\"># \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c python \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043b\u044f Jupyter \u0438\u0437 python3.8 (\u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f site-packages) \u0432 python3.7 cp -R \/home\/andrey\/.local\/lib\/python3.8\/site-packages \/home\/andrey\/.local\/lib\/python3.7\/site-packages sudo chmod -R 777 \/home\/andrey\/.local\/lib\/python3.7\/site-packages # \u041f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u043e\u0439 \u0432 notebook\u2019\u0435 Jupiter \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0439\u0442\u0435 \u044f\u0432\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 pythhon 3.7 %%script \/usr\/bin\/python3.7<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0435\u0449\u0451 \u0440\u0430\u0437 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043d\u043e\u0432\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443:<\/p>\n<p><code>py4j.protocol.Py4JJavaError: An error occurred while calling o31.load.<br \/> : org.apache.spark.sql.AnalysisException: Failed to find data source: kafka. Please deploy the application as per the deployment section of \"Structured Streaming + Kafka Integration Guide\".;<\/code><\/p>\n<p>\u0418\u0434\u0451\u043c \u0438\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u0438\u0447\u0438\u043d\u044b \u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f. \u041d\u0430\u0445\u043e\u0434\u0438\u043c \u0442\u043e, \u0447\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 config\u2019e spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0443 jar-\u043d\u0438\u043a\u043e\u0432 \u0434\u043b\u044f Kafka. \u041f\u043e\u043c\u0438\u043c\u043e \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u00abpyspark.streaming.kafka\u00bb.<\/p>\n<pre><code class=\"bash\">.config(\"spark.jars\",\"\/home\/andrey\/spark_jars\/spark-sql-kafka-0-10_2.11-2.4.4.jar,\/home\/andrey\/spark_jars\/kafka-clients-0.10.1.0.jar\")<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0451 \u0433\u043e\u0442\u043e\u0432\u043e \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"python\">%%script \/usr\/bin\/python3.7  checkpoint_path = \".\/checkpoint\/test_2\" kafka_servers = \"localhost:9092\" topic = \"testTopic\"  import findspark findspark.init('\/home\/andrey\/spark-2.4.4-bin-hadoop2.7')  from pyspark.sql import SparkSession from pyspark.streaming.kafka import KafkaUtils   spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_test_2\")  .config(\"spark.jars\",\"\/home\/andrey\/spark_jars\/spark-sql-kafka-0-10_2.11-2.4.4.jar,\/home\/andrey\/spark_jars\/kafka-clients-0.10.1.0.jar\")           .getOrCreate())  adViewsDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"earliest\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   query = adViewsDF.writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h2>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<p>\u041a\u0430\u043a \u0443\u0436\u0435 \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b \u0440\u0430\u043d\u0435\u0435, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0434\u0432\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u0430-\u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u043d\u0430 Python, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u0441\u044b\u043b\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 Kafka, \u0438 1 csv-\u0444\u0430\u0439\u043b\u0438\u043a. \u041e \u043d\u0438\u0445 \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443:<\/p>\n<p><strong>producerAdViews.py<\/strong> \u2013 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430\u0445 \u0440\u0435\u043a\u043b\u0430\u043c\u044b \u043d\u0430 \u0441\u0430\u0439\u0442\u0430\u0445. \u041f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 json \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b:<\/p>\n<ul>\n<li>\n<p>event_time \u2013 \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0441 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0438\u043b\u0438 \u0432\u044b\u0447\u0438\u0442\u0430\u043d\u0438\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0439 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u044b;<\/p>\n<\/li>\n<li>\n<p>ad_id \u2013 ID \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430 (\u0438\u0437 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0430);<\/p>\n<\/li>\n<li>\n<p>country \u2013 \u0441\u0442\u0440\u0430\u043d\u0430 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0437\u0430\u0448\u043b\u0438 \u043d\u0430 \u0441\u0430\u0439\u0442;<\/p>\n<\/li>\n<li>\n<p>site;<\/p>\n<\/li>\n<li>\n<p>view_duration \u2013 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0440\u0435\u043a\u043b\u0430\u043c\u044b.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u0441\u043a\u0440\u0438\u043f\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u0442\u0430\u043a, \u0447\u0442\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0441 \u043f\u0430\u0443\u0437\u043e\u0439 \u0432 1 \u0441\u0435\u043a\u0443\u043d\u0434\u0443 \u0438 \u0432\u0441\u0435\u0433\u043e \u0442\u0430\u043a\u0438\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c\u0441\u044f 60. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u044d\u0442\u0443 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443.<\/p>\n<details class=\"spoiler\">\n<summary>producerAdViews.py<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">from kafka import KafkaProducer     from json import dumps from kafka.errors import KafkaError from time import sleep from numpy.random import choice, randint import time import datetime  def getRandomValue():     new_dict = {}          country_list = ['ISL','DEU','SWE','ESP', 'UGA','JPN']     site_list = ['site1.ru','site2.com','site3.com','site4.es','site5.de','site6.jp',                  'site7.ru','site8.com','site9.com','site10.es','site11.de','site12.jp']     ts = time.time() + randint(-15, 0)     event_time = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')           new_dict['event_time'] = event_time     new_dict['ad_id'] = randint(1, 5)     new_dict['country'] = choice(country_list)     new_dict['site'] = choice(site_list)     new_dict['viewing_duration'] = randint(1, 15)          return new_dict  producer = KafkaProducer(bootstrap_servers=['localhost:9092'],                           value_serializer = lambda x:dumps(x).encode('utf-8'),                          compression_type = 'gzip') topic_name = 'adViews'  k = 0 while k &lt; 60:     k += 1     random_data = getRandomValue()     print(random_data)     try:         future = producer.send(topic = topic_name, value = random_data)         message_metadata = future.get(timeout=10)          print(f\"\"\"[+] message_metadata: {message_metadata.topic}, partition: {message_metadata.partition}, offset: {message_metadata.offset}\"\"\")     except Exception as e:         print(f\">>> Error: {e}\")     finally:         producer.flush()     sleep(1)  producer.close()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p><strong>producerAdViewsAndClicks.py<\/strong> \u2013 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0434\u0432\u0443\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430\u0445 \u0438 \u043a\u043b\u0438\u043a\u0430\u0445 \u043f\u043e \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u043c \u0431\u043b\u043e\u043a\u0430\u043c. \u0414\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u043e\u0432 \u0432\u0441\u0451 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 \u0441\u043a\u0440\u0438\u043f\u0442\u0443 \u0438 \u0434\u043b\u044f \u043a\u043b\u0438\u043a\u043e\u0432 \u043f\u043e\u0447\u0442\u0438 \u0442\u0430\u043a \u0436\u0435:<\/p>\n<ul>\n<li>\n<p>click_time \u2013 \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0441 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0438\u043b\u0438 \u0432\u044b\u0447\u0438\u0442\u0430\u043d\u0438\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0439 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u044b;<\/p>\n<\/li>\n<li>\n<p>ad_id;<\/p>\n<\/li>\n<li>\n<p>country;<\/p>\n<\/li>\n<li>\n<p>site.<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>producerAdViewsAndClicks.py<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">from kafka import KafkaProducer     from json import dumps from kafka.errors import KafkaError from time import sleep from numpy.random import choice, randint import time import datetime  def getRandomValue():     adViews_dict = {}     adClicks_dict = {}          country_list = ['ISL','DEU','SWE','ESP','UGA','JPN','BRA']     site_list = ['site1.ru','site2.com','site3.com','site4.es','site5.de','site6.jp',                  'site7.ru','site8.com','site9.com','site10.es','site11.de','site12.jp']     ts = time.time() + randint(-10, 0)     event_time = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')           ts = time.time() + randint(-20, 0)     click_time = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')           ad_id = randint(1, 5)     country = choice(country_list)     site = choice(site_list)     viewing_duration = randint(1, 15)          adViews_dict['event_time'] = event_time     adViews_dict['ad_id'] = ad_id     adViews_dict['country'] = country     adViews_dict['site'] = site     adViews_dict['viewing_duration'] = viewing_duration          adClicks_dict['click_time'] = click_time     adClicks_dict['ad_id'] = ad_id     adClicks_dict['country'] = country     adClicks_dict['site'] = site          return adViews_dict, adClicks_dict  producer1 = KafkaProducer(bootstrap_servers=['localhost:9092'],                           value_serializer = lambda x:dumps(x).encode('utf-8'),                          compression_type = 'gzip')  producer2 = KafkaProducer(bootstrap_servers=['localhost:9092'],                           value_serializer = lambda x:dumps(x).encode('utf-8'),                          compression_type = 'gzip')  k = 0 while k &lt; 60:     k += 1     random_data_views, random_data_clicks = getRandomValue()     print(random_data_views)     try:         res = producer1.send(topic = 'adViews', value = random_data_views)         msg = res.get(timeout=10)         print(f\"\"\" [+] message_metadata: {msg.topic}, partition: {msg.partition}, offset: {msg.offset}\"\"\")     except Exception as e:         print(f\">>> Error: {e}\")     finally:         producer.flush()          click_is_happend = randint(0, 10)     if click_is_happend > 5:         print(\"+ click:\")         print(random_data_clicks)         try:             res = producer2.send(topic = 'adClicks', value = random_data_clicks)             msg = res.get(timeout=10)             print(f\"\"\" [+] message_metadata: {msg.topic}, partition: {msg.partition}, offset: {msg.offset}\"\"\")         except Exception as e:             print(f\">>> Error: {e}\")         finally:             producer.flush()     print(\"-------------------------------------------------------------------------------------------------\")     sleep(1)  producer1.close() producer2.close()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412 \u043e\u0431\u043e\u0438\u0445 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430\u0445 \u0432 \u043f\u043e\u043b\u0435 event_time, \u0430 \u0442\u0430\u043a\u0436\u0435 click_time \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043a\u043b\u043e\u043d\u044f\u0442\u0441\u044f \u043e\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043d\u0430 +-10 \u0438 20 \u0441\u0435\u043a\u0443\u043d\u0434 \u2013 \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u043e\u0434\u044f\u043d\u044b\u0445 \u0437\u043d\u0430\u043a\u043e\u0432 \u0441 \u043e\u043a\u043d\u0430\u043c\u0438 (withWatermark(); window()), \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435, \u0432 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0438 \u0434\u0432\u0443\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 (Stream-Stream Join).<\/p>\n<p><strong>ad_parameters.csv<\/strong> \u2013 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0440\u0430\u043d\u0441\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043d\u0430 \u0441\u0430\u0439\u0442\u044b. \u042d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u0435\u043d \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 Join \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u0442\u043e\u043a\u043e\u043c \u0438 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 (Stream join Static DataFrame). \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0444\u0430\u0439\u043b\u0430 \u0432\u0435\u0441\u044c\u043c\u0430 \u043f\u0440\u043e\u0441\u0442\u0430\u044f:<\/p>\n<ul>\n<li>\n<p>ad_id;<\/p>\n<\/li>\n<li>\n<p>category \u2013 \u043a\u0440\u0430\u0442\u043a\u043e\u0435 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u0440\u0435\u043a\u043b\u0430\u043c\u044b;<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>ad_block_parameters.csv<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"bash\">ad_idcategory 1clothes 2games 3electronics 4cars 5travel 6books<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h2>Kafka \u0438 Structured Streaming<\/h2>\n<p>\u041d\u0438\u0436\u0435 \u2013 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0447\u0442\u0435\u043d\u0438\u044f \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 Kafka, \u0442\u0430\u043a \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043d\u0430 \u0432\u0441\u0435 \u0441\u043b\u0443\u0447\u0430\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432\u043e\u0439 \u0436\u0438\u0437\u043d\u0438 (\u043f\u043e\u0447\u0442\u0438 \u043d\u0430 \u0432\u0441\u0435). \u041f\u0440\u0438\u043d\u0446\u0438\u043f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u043f\u0440\u043e\u0441\u0442 \u2013 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0439\u0442\u0435 Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0437\u0430\u0442\u0435\u043c \u0441\u043a\u0440\u0438\u043f\u0442 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p><strong>\u0427\u0442\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0443<\/strong><\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0440\u0430\u0437\u0443 \u043f\u043e \u043c\u0435\u0440\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u043e\u0442 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u044b \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0442 \u043a\u0430\u0436\u0434\u0443\u044e \u0441\u0435\u043a\u0443\u043d\u0434\u0443. \u0414\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c:<\/p>\n<pre><code class=\"python\">kafkaDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"earliest\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   query = kafkaDF.writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_1_1)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_1_1\" kafka_servers = \"localhost:9092\" topic = \"adViews\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_1_1\")         .getOrCreate())  adViewsDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"earliest\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   query = adViewsDF.writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7c0\/029\/796\/7c00297961eaf4b999b824ef673228ef.png\" width=\"877\" height=\"255\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7c0\/029\/796\/7c00297961eaf4b999b824ef673228ef.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435:<br \/><\/strong><em>\u0415\u0441\u043b\u0438 \u0432\u044b \u0431\u0443\u0434\u0435\u0442\u0435 \u043e\u0442\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0432 Jupyter \u0438 \u0432 \u043e\u0434\u043d\u043e\u043c notebook\u2019\u0435 \u0443 \u0432\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u043d\u044b\u0445 spark-\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432, \u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0439\u0442\u0435 \u044f\u0434\u0440\u043e Notebook\u2019\u0430 \u043f\u0435\u0440\u0435\u0434 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c \u043d\u043e\u0432\u043e\u0433\u043e Spark-\u0441\u043a\u0440\u0438\u043f\u0442\u0430.<\/em><\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u0430 \u0438 \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u0442\u044c \u0432 \u043d\u0451\u043c \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430 \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u00abprocessingTime\u00bb. \u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0440\u0430\u0437\u043c\u0435\u0440 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u0430 \u0432 5 \u0441\u0435\u043a\u0443\u043d\u0434. \u0422\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0430\u0440\u0441\u0438\u043d\u0433 json-\u043f\u043e\u043b\u0435\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u00abfrom_json\u00bb \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u044b. \u042d\u0442\u043e \u0443\u0436\u0435 \u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0438 \u043e\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e, \u0433\u0434\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0438\u043b\u0438\u0441\u044c \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u043e\u0439. \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0440\u0430\u0431\u043e\u0442\u0430\u043b, \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0430\u0440\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a: \u00abpyspark.sql.functions\u00bb \u0438 \u00abpyspark.sql.types\u00bb.<\/p>\n<pre><code class=\"python\">schema = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  query = kafkaDF.select(from_json(col(\"value\"), schema).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .trigger(processingTime='5 seconds') \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u043f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_1_2) <\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_1_2\" kafka_servers = \"localhost:9092\" topic = \"adViews\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql.types import *  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_1_2\")         .getOrCreate())  kafkaDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"earliest\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   schema = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  query = kafkaDF.select(from_json(col(\"value\"), schema).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .trigger(processingTime='5 seconds') \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7b1\/1c4\/a24\/7b11c4a2464d8ad4c2e10612640caa4e.png\" width=\"423\" height=\"323\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7b1\/1c4\/a24\/7b11c4a2464d8ad4c2e10612640caa4e.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430\u0434\u043f\u0438\u0441\u0438 \u043d\u0430\u043f\u043e\u0434\u043e\u0431\u0438\u0435 \u00abBatch 7, Batch 8\u00bb \u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0442 \u043f\u043e\u0440\u044f\u0434\u043a\u043e\u0432\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u0430 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 checkpoint\u2019\u0430. <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b12\/0f5\/8d4\/b120f58d4a4f433126fda39f661f9f92.png\" width=\"710\" height=\"391\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b12\/0f5\/8d4\/b120f58d4a4f433126fda39f661f9f92.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u2013 8-\u0433\u043e offset\u2019\u0430<\/p>\n<p><code>{\"batchWatermarkMs\":0,\"batchTimestampMs\":1654753995003,\"conf\":{\"spark.sql.streaming.stateStore.providerClass\":\"org.apache.spark.sql.execution.streaming.state.HDFSBackedStateStoreProvider\",\"spark.sql.streaming.join.stateFormatVersion\":\"2\",\"spark.sql.streaming.stateStore.compression.codec\":\"lz4\",\"spark.sql.streaming.flatMapGroupsWithState.stateFormatVersion\":\"2\",\"spark.sql.streaming.multipleWatermarkPolicy\":\"min\",\"spark.sql.streaming.aggregation.stateFormatVersion\":\"2\",\"spark.sql.shuffle.partitions\":\"200\"}}<br \/>{\"adViews\":{\"1\":635,\"0\":620}}<\/code><\/p>\n<p>\u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0442\u0435\u043a\u0441\u0442\u0430 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043d\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0430, \u0430 \u0432\u043e\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u2013 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u043e\u043c, \u043d\u0430 \u043a\u0430\u043a\u043e\u043c \u0441\u043c\u0435\u0448\u0435\u043d\u0438\u0438 (\u043f\u043e\u0434\u043e\u0431\u0438\u0435 id-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f) \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0437 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u043e\u0441\u044c \u0447\u0442\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 Kafka \u0432 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442. \u0422\u043e \u0435\u0441\u0442\u044c \u0432 8-\u043c\u043e\u043c \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u0435 \u0434\u043b\u044f \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438 1 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 635 \u2013 1 = 634, \u0430 \u0434\u043b\u044f \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438 0 \u044d\u0442\u043e 620 \u2013 1 = 619.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u043b \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 \u00abproducerAdViews.py\u00bb.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f51\/334\/c60\/f51334c607568d1f8d3e69f5b82f0e62.png\" width=\"965\" height=\"307\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f51\/334\/c60\/f51334c607568d1f8d3e69f5b82f0e62.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041a\u0440\u0430\u0441\u043d\u043e\u0439 \u0440\u0430\u043c\u043a\u043e\u0439 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u044b \u0442\u0435 5 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043f\u0430\u043b\u0438 \u0432 8-\u0439 \u041c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442 (\u0441 5 \u0441\u0435\u043a\u0443\u043d\u0434\u043d\u044b\u043c \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c). \u0422\u0430\u043a\u0436\u0435 \u043d\u0430 \u043d\u0451\u043c \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u044b \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0437 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439: 1 \u2013 634, 0 \u2013 619. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u043e\u0441\u043b\u0435 \u043f\u0430\u0434\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u2013 \u0441 \u043a\u0430\u043a\u0438\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043d\u0430\u0434\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0447\u0442\u0435\u043d\u0438\u0435.<\/p>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 ChekPoint\u2019\u043e\u0432 \u0432 Spark \u0438 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b Kafka \u043e\u043f\u0438\u0441\u0430\u043d \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438, \u0432 \u0431\u043b\u043e\u043a\u0430\u0445 \u0441 \u0442\u0435\u043e\u0440\u0438\u0435\u0439.<\/p>\n<p>\u041f\u0440\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043e\u0448\u0438\u0431\u043a\u0430\/\u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u00abStreamingQueryException: Writing job aborted\u00bb. \u042d\u0442\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e Spark \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 checkpoint\u2019a \u0441 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043f\u0430\u0443\u0437\u044b \u0441 \u043d\u043e\u0432\u044b\u043c \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u043e\u043c \u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0435\u0433\u043e \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 (\u0438\u043b\u0438 \u0432\u044b\u0432\u043e\u0434\u0430 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c). \u042d\u0442\u043e, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442, \u0435\u0441\u043b\u0438 \u0432\u0430\u0448\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u044f\u043b\u043e \u0432 \u043f\u0430\u0443\u0437\u0435 \u0438 \u043d\u0435\u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0443\u0436\u0435 \u0443\u0441\u043f\u0435\u043b\u0438 \u0443\u0434\u0430\u043b\u0438\u0442\u044c\u0441\u044f \u0438\u0445 Kafka. \u0414\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432 \u0442\u043e\u043f\u0438\u043a\u0435 Kafka \u043c\u043e\u0436\u043d\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u00ab<strong>retention.ms<\/strong>\u00bb.<\/p>\n<p>\u0411\u044b\u0441\u0442\u0440\u043e \u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0434\u0432\u0443\u043c\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438:<\/p>\n<p><strong>1)<\/strong> \u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043e\u0447\u0438\u0449\u0435\u043d\u0438\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 checkpoint \u0438 \u0447\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u0430 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c\u0441\u044f \u00ab\u0441 \u0447\u0438\u0441\u0442\u043e\u0433\u043e \u043b\u0438\u0441\u0442\u0430\u00bb. \u041c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0441\u0447\u0438\u0442\u0430\u0442\u044c\u0441\u044f \u043e\u043f\u044f\u0442\u044c \u0441 1;<\/p>\n<pre><code class=\"python\">def remove_thing(path):     if os.path.isdir(path):         shutil.rmtree(path)     else:         os.remove(path)  def empty_directory(path):     for i in glob.glob(os.path.join(path, '*')):         remove_thing(i)  try:     empty_directory(checkpoint_path) except Exception as e:     print(\"Exception: \", e)<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_1_3)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os import shutil import glob  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_1_3\" kafka_servers = \"localhost:9092\" topic = \"adViews\"  def remove_thing(path):     if os.path.isdir(path):         shutil.rmtree(path)     else:         os.remove(path)  def empty_directory(path):     for i in glob.glob(os.path.join(path, '*')):         remove_thing(i)  try:     empty_directory(checkpoint_path) except Exception as e:     print(\"Exception: \", e)  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql.types import *   kafka_servers = \"localhost:9092\" topic = \"adViews\"  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_1_3\")         .getOrCreate())  kafkaDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"earliest\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   schema = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  query = kafkaDF.select(from_json(col(\"value\"), schema).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .trigger(processingTime='5 seconds') \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p><strong>2)<\/strong> \u0423\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u043f\u0446\u0438\u044e \u00abfailOnDataLoss &#8212; false\u00bb.<\/p>\n<pre><code class=\"python\">.option(\"failOnDataLoss\", \"false\") \\<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_1_4)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_1_4\" kafka_servers = \"localhost:9092\" topic = \"adViews\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql.types import *  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_1_4\")         .getOrCreate())  kafkaDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"earliest\") \\             .option(\"failOnDataLoss\", \"false\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   schema = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  query = kafkaDF.select(from_json(col(\"value\"), schema).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .trigger(processingTime='5 seconds') \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412\u043e \u0432\u0441\u0435\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u0445 \u0432\u044b \u043f\u043e\u0442\u0435\u0440\u044f\u0435\u0442\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043d\u043e \u044d\u0442\u043e \u043d\u0435 \u043f\u043e\u043c\u0435\u0448\u0430\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u0440\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 Kafka.<\/p>\n<p><strong>\u0427\u0442\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 Kafka \u0432 Static DataFrame<\/strong><\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u0448 \u043f\u043e\u0442\u043e\u043a \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u043b \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0437\u0430 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043f\u0435\u0440\u0438\u043e\u0434, \u043d\u043e \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432 Kafka \u043e\u043d\u0438 \u0432\u0441\u0451 \u0435\u0449\u0451 \u043b\u0435\u0436\u0430\u0442 \u0438\u043b\u0438 \u0432\u0430\u043c \u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0435\u0441\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u0434\u0430\u043d\u043d\u044b\u0445, \u0432 Spark \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e. \u041d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043b\u0435\u0432\u0443\u044e \u0438 \u043f\u0440\u0430\u0432\u0443\u044e \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 Kafka \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 \u00abread\u00bb \u0432\u043c\u0435\u0441\u0442\u043e \u00abreadstream\u00bb.<\/p>\n<pre><code class=\"python\">kafkaDF = spark \\             .read \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"\"\"{\"adViews\":{\"1\":910,\"0\":908}}\"\"\") \\             .option(\"endingOffsets\", \"\"\"{\"adViews\":{\"1\":928,\"0\":925}}\"\"\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_1_6)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_1_6\" kafka_servers = \"localhost:9092\" topic = \"adViews\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql.types import *  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_1_2\")         .getOrCreate())  kafkaDF = spark \\             .read \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"\"\"{\"adViews\":{\"1\":910,\"0\":908}}\"\"\") \\             .option(\"endingOffsets\", \"\"\"{\"adViews\":{\"1\":928,\"0\":925}}\"\"\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   schema = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  batchDataDF = kafkaDF.select(from_json(col(\"value\"), schema).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\              batchDataDF.show()  batchDataDF.write.format(\"json\") \\             .mode(\"overwrite\") \\             .save(\".\/results\/ex_1_6\")<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/601\/cf4\/acf\/601cf4acf0edbb06ce01a172f6db782b.png\" width=\"451\" height=\"334\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/601\/cf4\/acf\/601cf4acf0edbb06ce01a172f6db782b.png\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>\u0427\u0442\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/strong><\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u043f\u0435\u0440\u0432\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0439 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442 \u0441\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0438\u0437 \u0442\u043e\u043f\u0438\u043a\u0430 Kafka, \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u0432 \u043e\u043f\u0446\u0438\u0438 \u00abstartingOffests\u00bb \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u00ablatest\u00bb.<\/p>\n<pre><code class=\"python\">kafkaDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"latest\") \\             .option(\"failOnDataLoss\", \"false\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\") <\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_1_5)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_1_5\" kafka_servers = \"localhost:9092\" topic = \"adViews\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql.types import *  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_1_5\")         .getOrCreate())  kafkaDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"latest\") \\             .option(\"failOnDataLoss\", \"false\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   schema = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  query = kafkaDF.select(from_json(col(\"value\"), schema).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .trigger(processingTime='5 seconds') \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 Kafka \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c (\u0442\u043e\u0447\u043d\u0435\u0435 \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c) \u0437\u0430 \u0441\u0447\u0451\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0441\u0430\u043c\u043e\u0433\u043e \u0442\u043e\u043f\u0438\u043a\u0430. \u0418\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u0432\u0440\u0435\u043c\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432 \u0442\u043e\u043f\u0438\u043a\u0435 \u0434\u043e 1 \u0441\u0435\u043a\u0443\u043d\u0434\u044b, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432\u0441\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u0414\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445.<\/p>\n<pre><code class=\"bash\">#purge kafka topic (change retention)  bin\/kafka-configs.sh --bootstrap-server localhost:9092 --alter --topic transaction --add-config retention.ms=1000<\/code><\/pre>\n<p><strong>\u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445<\/strong><\/p>\n<p>Structured Streaming \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u043b\u0435\u0433\u043a\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u043f\u0446\u0438\u044e \u00abfilter\u00bb \u0438 \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0443\u0441\u043b\u043e\u0432\u0438\u0435. \u0414\u0430\u0432\u0430\u0439\u0442\u0435, \u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u0435 \u043f\u043e\u043a\u0430\u0437\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b\u043b\u0438 \u0441\u0434\u0435\u043b\u0430\u043d\u044b \u0438\u0437 \u0423\u0433\u0430\u043d\u0434\u044b (UGA).<\/p>\n<pre><code class=\"python\">query = kafkaDF.select(from_json(col(\"value\"), schema).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .filter(\"t.country = 'UGA'\") \\             .writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .trigger(processingTime='5 seconds') \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_2_1)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_2_1\" kafka_servers = \"localhost:9092\" topic = \"adViews\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql.types import *   kafka_servers = \"localhost:9092\" topic = \"adViews\"  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_2_1\")         .getOrCreate())  kafkaDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"latest\") \\             .option(\"failOnDataLoss\", \"false\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   schema = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  query = kafkaDF.select(from_json(col(\"value\"), schema).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .filter(\"t.country = 'UGA'\") \\             .writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .trigger(processingTime='5 seconds') \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0430\u043a\u0435\u0442\u044b \u043f\u0440\u0438\u0448\u043b\u0438 \u043f\u0443\u0441\u0442\u044b\u043c\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043b\u0438 \u043f\u043e\u043a\u0430\u0437\u043e\u0432 \u043f\u043e \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0444\u0438\u043b\u044c\u0442\u0440\u0443.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/aa0\/b1f\/032\/aa0b1f0322a75988c72a19a99adf33c7.png\" alt=\"\u0414\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 Producer\u2019\u0430\" title=\"\u0414\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 Producer\u2019\u0430\" width=\"805\" height=\"379\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/aa0\/b1f\/032\/aa0b1f0322a75988c72a19a99adf33c7.png\"\/><figcaption>\u0414\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 Producer\u2019\u0430<\/figcaption><\/figure>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/742\/41a\/219\/74241a219b413cee81a991127fd674b1.png\" alt=\"\u041c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u044b \u043f\u043e\u0441\u043b\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438\" title=\"\u041c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u044b \u043f\u043e\u0441\u043b\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438\" width=\"457\" height=\"447\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/742\/41a\/219\/74241a219b413cee81a991127fd674b1.png\"\/><figcaption>\u041c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u044b \u043f\u043e\u0441\u043b\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438<\/figcaption><\/figure>\n<p>\u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0438 \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u043c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u0435 \u043f\u043e\u043a\u0430\u0437\u044b, \u0447\u0442\u043e \u0431\u044b\u043b\u0438 \u0432 \u0415\u0432\u0440\u043e\u043f\u0435\u0439\u0441\u043a\u0438\u0445 \u0441\u0442\u0440\u0430\u043d\u0430\u0445 \u0438 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e \u0431\u043e\u043b\u0435\u0435 4 \u0441\u0435\u043a\u0443\u043d\u0434.<\/p>\n<pre><code class=\"python\">query = kafkaDF.select(from_json(col(\"value\"), schema).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .filter(\"t.country in ('DEU','SWE','ESP') and t.viewing_duration > 4\") \\             .writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .trigger(processingTime='5 seconds') \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_2_2)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_2_2\" kafka_servers = \"localhost:9092\" topic = \"adViews\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql.types import *   kafka_servers = \"localhost:9092\" topic = \"adViews\"  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_2_2\")         .getOrCreate())  kafkaDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"latest\") \\             .option(\"failOnDataLoss\", \"false\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   schema = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  query = kafkaDF.select(from_json(col(\"value\"), schema).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .filter(\"t.country in ('DEU','SWE','ESP') and t.viewing_duration > 4\") \\             .writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .trigger(processingTime='5 seconds') \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p><strong>Join \u0441\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c DataFrame <\/strong><\/p>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438\u0437 \u0442\u043e\u043f\u0438\u043a\u0430 Kafka \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u0438\u0437 csv \/ json \u0444\u0430\u0439\u043b\u0430 \u0438\u043b\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0411\u0414. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c join, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043a\u043b\u044e\u0447, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0442\u044c\u0441\u044f.<\/p>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 \u043d\u0430\u0448\u0435\u0439 \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439 \u00a0\u0432 \u0444\u0430\u0439\u043b\u0435 \u00abad_parameters.csv\u00bb \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f\u0445 \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u043e\u0432. \u0412 \u043d\u0451\u043c \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435 &lt;ad_id>, \u043a\u0430\u043a \u0438 \u0432 \u043f\u043e\u0442\u043e\u043a\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u043e \u043d\u0438\u043c \u0438 \u0431\u0443\u0434\u0435\u043c \u0434\u0436\u043e\u0439\u043d\u0438\u0442\u044c\u0441\u044f. Spark \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u0441\u0435 \u0442\u0438\u043f\u043e\u0432\u044b\u0435 SQL \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f: INNER, LEFT OUTER, RIGHT OUTER, LEFT ANTI, LEFT SEMI, CROSS, SELF JOIN. \u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043d\u0438\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0451\u043d inner join \u0434\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u0440\u0435\u043a\u043b\u0430\u043c\u044b. <\/p>\n<pre><code class=\"python\">query = adViewsDF.select(from_json(col(\"value\"), schemaAdViews).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .join(adParametersDF, \"ad_id\") \\             .select(\"event_time\", \"ad_id\", \"category\", \"country\", \"site\", \"viewing_duration\") \\             .writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .trigger(processingTime='5 seconds') \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_3_1)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_3_1\" kafka_servers = \"localhost:9092\" topic = \"adViews\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql.types import *  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_3_1\")         .getOrCreate())  schemaAdParam = \"ad_id int, category string\"  adParametersDF = spark \\                 .read \\                 .format(\"csv\") \\                 .option(\"header\", \"true\") \\                 .option(\"delimiter\",\"\\t\") \\                 .schema(schemaAdParam) \\                 .load(\".\/files\/ad_parameters.csv\")  #adParametersDF.show() #adParametersDF.printSchema()  adViewsDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"latest\") \\             .option(\"failOnDataLoss\", \"false\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   schemaAdViews = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  query = adViewsDF.select(from_json(col(\"value\"), schemaAdViews).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .join(adParametersDF, \"ad_id\") \\             .select(\"event_time\", \"ad_id\", \"category\", \"country\", \"site\", \"viewing_duration\") \\             .writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .trigger(processingTime='5 seconds') \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/915\/8d6\/67d\/9158d667d7827224acf18d7c6e9a2a81.png\" alt=\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f StreamDataFrame with DataFrame\" title=\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f StreamDataFrame with DataFrame\" width=\"501\" height=\"321\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/915\/8d6\/67d\/9158d667d7827224acf18d7c6e9a2a81.png\"\/><figcaption>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f StreamDataFrame with DataFrame<\/figcaption><\/figure>\n<p>\u0410 \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u043c\u0435\u0440 \u0431\u044b\u043b \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0439, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0444\u0438\u043b\u044c\u0442\u0440 \u00ab\u043f\u043e\u043a\u0430\u0437\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u2018clothes\u2019\u00bb.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_3_2)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_3_2\" kafka_servers = \"localhost:9092\" topic = \"adViews\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql.types import *  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_3_2\")         .getOrCreate())  schemaAdParam = \"ad_id int, category string\"  adParametersDF = spark \\                 .read \\                 .format(\"csv\") \\                 .option(\"header\", \"true\") \\                 .option(\"delimiter\",\"\\t\") \\                 .schema(schemaAdParam) \\                 .load(\".\/files\/ad_parameters.csv\")  #adParametersDF.show() #adParametersDF.printSchema()  adViewsDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"latest\") \\             .option(\"failOnDataLoss\", \"false\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   schemaAdViews = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  query = adViewsDF.select(from_json(col(\"value\"), schemaAdViews).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .join(adParametersDF, \"ad_id\") \\             .select(\"event_time\", \"ad_id\", \"category\", \"country\", \"site\", \"viewing_duration\") \\             .filter(\"category = 'clothes'\") \\             .writeStream.format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .trigger(processingTime='5 seconds') \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041e\u0431\u043e\u0433\u0430\u0449\u0451\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0434\u0430\u043b\u0435\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u0435\u0449\u0451 \u043e\u0434\u0438\u043d \u0442\u043e\u043f\u0438\u043a Kafka.<\/p>\n<pre><code class=\"python\">query = adViewsDF.select(from_json(col(\"value\"), schemaAdViews).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .join(adParametersDF, \"ad_id\") \\             .select(to_json(struct(\"event_time\", \"ad_id\", \"category\", \"country\", \"site\", \"viewing_duration\")).alias(\"value\")) \\             .writeStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"topic\",\"adDescription\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .trigger(processingTime='5 seconds') \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/566\/002\/082\/566002082efdf04aef1b9680b2a35bd0.png\" width=\"723\" height=\"189\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/566\/002\/082\/566002082efdf04aef1b9680b2a35bd0.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0444\u0430\u0439\u043b\u044b \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432. \u0421\u0430\u043c\u044b\u0435 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0435 \u2013 \u044d\u0442\u043e json, parquet \u0438 csv. \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u044f \u044d\u0442\u0438 \u0444\u0430\u0439\u043b\u044b \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0447\u0438\u0442\u0430\u0435\u0442 Hive-\u0442\u0430\u0431\u043b\u0438\u0446\u0430, \u0432\u044b \u043f\u043e \u0441\u0443\u0442\u0438 \u0431\u0443\u0434\u0435\u0442\u0435 \u0434\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u044d\u0442\u0443 \u0441\u0430\u043c\u0443\u044e Hive-\u0442\u0430\u0431\u043b\u0438\u0446\u0443 (\u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u2013 \u0431\u0443\u0434\u044c\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b \u0441\u043e \u0441\u0445\u0435\u043c\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445).<\/p>\n<p><strong>\u0410\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445<\/strong><\/p>\n<p>\u041e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u0441 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430. \u0418 \u043f\u043e\u0434 \u044d\u0442\u043e\u0439 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u043e\u0439 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u0442\u044c\u0441\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u044b: \u0441\u0440\u0435\u0434\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0441\u0443\u043c\u043c\u044b, \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430, \u043c\u0438\u043d\u0438\u043c\u0443\u043c, \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0436\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u043e\u0434\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0432\u0441\u0435 \u0442\u0430\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u044f c \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0440\u0435\u043a\u043b\u0430\u043c\u044b \u0432 \u0440\u0430\u0437\u0440\u0435\u0437\u0435 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0440\u0430\u043d.<\/p>\n<pre><code class=\"python\">query = adViewsDF.select(from_json(col(\"value\"), schemaAdViews).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .groupBy(\"country\") \\             .agg(count(\"*\").alias(\"count\"),                  min(\"viewing_duration\").alias(\"min\"),                  max(\"viewing_duration\").alias(\"max\"),                  sum(\"viewing_duration\").alias(\"sum\"),                  avg(\"viewing_duration\").alias(\"avg\")) \\             .writeStream \\             .format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .trigger(processingTime='5 seconds') \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/p>\n<p><code>AnalysisException: Append output mode not supported when there are streaming aggregations on streaming DataFrames\/DataSets without watermark;<\/code>   <\/p>\n<p>Spark \u0447\u0451\u0442\u043a\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u00ab\u0432\u043e\u0434\u044f\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u043a\u0430\u00bb.<\/p>\n<p>\u041d\u043e \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u0440\u0430\u0437\u0434\u0435\u043b\u0443 \u043f\u0440\u043e \u0432\u043e\u0434\u044f\u043d\u044b\u0435 \u0437\u043d\u0430\u043a\u0438, \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u2013 \u00a0\u043a\u0430\u043a \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u044e \u043d\u0430\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0438\u0437 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u043e\u0432. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u043c \u00ab<strong>foreachBatch(<\/strong>&lt;<em>userFunction<\/em>><strong>)<\/strong>\u00bb \u2013 \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u043e\u0439 \u043a \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u0443 \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u041f\u043e \u0441\u0443\u0442\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u044b \u0443\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0441\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u043c DataFram\u2019\u043e\u043c \u0438, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0432\u0441\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u044b.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0438\u0437 Structured Streaming \u0432 PostgreSQL-\u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u00abad_country_aggregations\u00bb. \u0412 \u044d\u0442\u043e\u043c \u0441\u043a\u0440\u0438\u043f\u0442\u0435 \u043a\u0430\u0436\u0434\u044b\u0435 10 \u0441\u0435\u043a\u0443\u043d\u0434 \u00ab\u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0439\u00bb \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u00abwriteToPostgres()\u00bb. \u0412 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0438 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0440\u0435\u043a\u043b\u0430\u043c\u044b \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0432\u0441\u0435\u0433\u043e \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u0430. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0432\u0438\u0434\u0435\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439.<\/p>\n<pre><code class=\"python\">def writeToPostgres(df, epoch_id):       intervalDF = df.agg(min(\"event_time\").alias(\"min_event_time\"),                            max(\"event_time\").alias(\"max_event_time\"))     min_event_time = intervalDF.head(1)[0][0]     max_event_time = intervalDF.head(1)[0][1]     agrDF = df.groupBy(\"country\") \\             .agg(count(\"*\").alias(\"count\"),                  min(\"viewing_duration\").alias(\"min\"),                  max(\"viewing_duration\").alias(\"max\"),                  sum(\"viewing_duration\").alias(\"sum\"),                  avg(\"viewing_duration\").alias(\"avg\")) \\             .select(\"country\",\"count\", \"min\", \"max\", \"sum\", \"avg\",                     concat(lit(min_event_time), lit(\" - \"), lit(max_event_time)).alias(\"time_interval\"))     agrDF.show(truncate=False)     agrDF.write \\         .format('jdbc') \\         .option(\"url\", \"jdbc:postgresql:\/\/\" + db_host) \\         .option(\"driver\", \"org.postgresql.Driver\") \\         .option(\"dbtable\", \"ad_country_aggregations\") \\         .option(\"user\", db_user) \\         .option(\"password\", db_password) \\         .mode(\"append\") \\         .save() . . . streamData = adViewsDF.select(from_json(col(\"value\"), schemaAdViews).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\  streamData.writeStream \\     .foreachBatch(writeToPostgres) \\     .option(\"checkpointLocation\", checkpoint_path) \\     .trigger(processingTime='10 seconds') \\     .start() \\     .awaitTermination()<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_4_2)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_4_1\" kafka_servers = \"localhost:9092\" import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_4_2\" kafka_servers = \"localhost:9092\" topic = \"adViews\" db_host = \"localhost:5432\/advertising\" db_user = \"developer\" db_password = \"123456\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql.types import *  def writeToPostgres(df, epoch_id):       intervalDF = df.agg(min(\"event_time\").alias(\"min_event_time\"),                            max(\"event_time\").alias(\"max_event_time\"))     min_event_time = intervalDF.head(1)[0][0]     max_event_time = intervalDF.head(1)[0][1]     agrDF = df.groupBy(\"country\") \\             .agg(count(\"*\").alias(\"count\"),                  min(\"viewing_duration\").alias(\"min\"),                  max(\"viewing_duration\").alias(\"max\"),                  sum(\"viewing_duration\").alias(\"sum\"),                  avg(\"viewing_duration\").alias(\"avg\")) \\             .select(\"country\",\"count\", \"min\", \"max\", \"sum\", \"avg\",                     concat(lit(min_event_time), lit(\" - \"), lit(max_event_time)).alias(\"time_interval\"))     agrDF.show(truncate=False)     agrDF.write \\         .format('jdbc') \\         .option(\"url\", \"jdbc:postgresql:\/\/\" + db_host) \\         .option(\"driver\", \"org.postgresql.Driver\") \\         .option(\"dbtable\", \"ad_country_aggregations\") \\         .option(\"user\", db_user) \\         .option(\"password\", db_password) \\         .mode(\"append\") \\         .save()  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_4_2\")         .config(\"spark.jars\",\"\/home\/andrey\/spark_jars\/postgresql-42.4.0.jar\")         .getOrCreate())  adViewsDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"latest\") \\             .option(\"failOnDataLoss\", \"false\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   schemaAdViews = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  streamData = adViewsDF.select(from_json(col(\"value\"), schemaAdViews).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\  streamData.writeStream \\     .foreachBatch(writeToPostgres) \\     .option(\"checkpointLocation\", checkpoint_path) \\     .trigger(processingTime='10 seconds') \\     .start() \\     .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 DataFram\u2019\u044b<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/98b\/b98\/5ad\/98bb985adad93708d9b05b888d581364.png\" width=\"633\" height=\"302\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/98b\/b98\/5ad\/98bb985adad93708d9b05b888d581364.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 PostgreSQL.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3a8\/f5c\/943\/3a8f5c943b708066c06968eee878aaed.png\" width=\"1077\" height=\"376\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3a8\/f5c\/943\/3a8f5c943b708066c06968eee878aaed.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0421\u043a\u0440\u0438\u043f\u0442\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 PostgreSQL \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p><strong>\u0412\u043e\u0434\u044f\u043d\u044b\u0435 \u0437\u043d\u0430\u043a\u0438 \u0438 \u0441\u043a\u043e\u043b\u044c\u0437\u044f\u0449\u0435\u0435 \u043e\u043a\u043d\u043e<\/strong><\/p>\n<p>\u0415\u0441\u043b\u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b <strong>withWatermark()<\/strong> \u0438 <strong>window()<\/strong> \u0432 Structured Streaming \u0432\u0430\u043c \u0445\u043e\u0440\u043e\u0448\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u0430, \u0442\u043e \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c, \u0430 \u0435\u0441\u043b\u0438 \u043d\u0435\u0442, \u0442\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u0441\u044f \u0441 \u0442\u0435\u043e\u0440\u0438\u0435\u0439 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u0438 \u0441\u043e \u0441\u0442\u0430\u0442\u044c\u0451\u0439 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 (\u0432 \u043d\u0435\u0439 \u0441\u043e\u0437\u0434\u0430\u0442\u0435\u043b\u0438 Spark\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u043b\u0438 \u043e \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u043e\u0434\u044f\u043d\u044b\u0445 \u0437\u043d\u0430\u043a\u043e\u0432 \u0438 \u0441\u043a\u043e\u043b\u044c\u0437\u044f\u0449\u0435\u0433\u043e \u043e\u043a\u043d\u0430): <a href=\"https:\/\/databricks.com\/blog\/2017\/05\/08\/event-time-aggregation-watermarking-apache-sparks-structured-streaming.html\">https:\/\/databricks.com\/blog\/2017\/05\/08\/event-time-aggregation-watermarking-apache-sparks-structured-streaming.html<\/a><\/p>\n<p>\u0414\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0444\u0438\u0447 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u044e \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430. \u0418 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438:<\/p>\n<ul>\n<li>\n<p>\u041f\u0435\u0440\u0438\u043e\u0434 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \/ \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u2013 10 \u0441\u0435\u043a\u0443\u043d\u0434 \u043f\u043e \u043f\u043e\u043b\u044e &lt;event_time>;<\/p>\n<\/li>\n<li>\n<p>\u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u043f\u043e \u043f\u043e\u043b\u044e  \u0438 \u043f\u043e\u043b\u044e &lt;event_time> \u0442\u0430\u043a \u0436\u0435 \u043a\u0430\u0436\u0434\u044b\u0435 10 \u0441\u0435\u043a\u0443\u043d\u0434;<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u043c\u0443 \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u044e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f &lt;event_time> \u0432 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0435 \u0447\u0430\u0441\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043a\u0438\u0434\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u0437 \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u0430 \u0438\u0437-\u0437\u0430 \u0441\u0432\u043e\u0435\u0439 \u00ab\u0437\u0430\u043f\u043e\u0437\u0434\u0430\u043b\u043e\u0441\u0442\u0438\u00bb. \u041e\u0441\u0442\u0430\u0432\u0448\u0438\u0435\u0441\u044f, \u043f\u0440\u043e\u0448\u0435\u0434\u0448\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 \u0441\u0432\u0435\u0436\u0435\u0441\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0431\u0443\u0434\u0443\u0442 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0438\u043e\u0434\u0430. \u0412\u0430\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0431\u0435\u0437 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f window() Spark \u043d\u0435 \u0434\u0430\u043b \u0431\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f (append).<\/p>\n<pre><code class=\"python\">query = adViewsDF.select(from_json(col(\"value\"), schemaAdViews).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .withWatermark(\"event_time\", \"10 seconds\") \\             .groupBy(\"country\", window(\"event_time\", \"10 seconds\").alias(\"timewindow\")) \\             .agg(count(\"*\").alias(\"count\"),                  min(\"viewing_duration\").alias(\"min\"),                  max(\"viewing_duration\").alias(\"max\"),                  sum(\"viewing_duration\").alias(\"sum\"),                  avg(\"viewing_duration\").alias(\"avg\")) \\             .writeStream \\             .format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_5_1)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_5_1\" kafka_servers = \"localhost:9092\" topic = \"adViews\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql.types import *  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_5_1\")         .getOrCreate())  adViewsDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"latest\") \\             .option(\"failOnDataLoss\", \"false\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   schemaAdViews = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  query = adViewsDF.select(from_json(col(\"value\"), schemaAdViews).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .withWatermark(\"event_time\", \"10 seconds\") \\             .groupBy(\"country\", window(\"event_time\", \"10 seconds\").alias(\"timewindow\")) \\             .agg(count(\"*\").alias(\"count\"),                  min(\"viewing_duration\").alias(\"min\"),                  max(\"viewing_duration\").alias(\"max\"),                  sum(\"viewing_duration\").alias(\"sum\"),                  avg(\"viewing_duration\").alias(\"avg\")) \\             .writeStream \\             .format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0438 \u0436\u0434\u0451\u043c, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u043a\u043e\u043f\u044f\u0442\u0441\u044f \u043f\u0435\u0440\u0432\u044b\u0435 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u044b \u0441 \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u0435\u0439. \u041f\u0435\u0440\u0432\u044b\u0439 \u043f\u0430\u043a\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0435\u0433\u043e \u0434\u0432\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0438 \u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u043a \u00ab09:30:00- 09:30:10\u00bb.<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/026\/cbb\/d4f\/026cbbd4fbee357bda95e57d3e9e0fad.png\" width=\"514\" height=\"120\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/026\/cbb\/d4f\/026cbbd4fbee357bda95e57d3e9e0fad.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043b\u043e\u0433\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/914\/812\/2ef\/9148122ef69420281c06dc5c7f099543.png\" width=\"995\" height=\"198\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/914\/812\/2ef\/9148122ef69420281c06dc5c7f099543.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0438\u0434\u0438\u043c \u0442\u0435 \u0441\u0430\u043c\u044b\u0435 \u0434\u0432\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043f\u043e\u043f\u0430\u0432\u0448\u0438\u0435 \u0432 \u043f\u0435\u0440\u0432\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e Spark \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u0432 \u0432 \u00ab\u0440\u043e\u0432\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u0445\u00bb. \u041f\u0443\u0441\u0442\u044c \u043f\u0435\u0440\u0432\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u043f\u043e &lt;event_time> \u0432 \u00ab09:30:04\u00bb \u2013 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0432 10 \u0441\u0435\u043a\u0443\u043d\u0434 \u0431\u0443\u0434\u0435\u0442 \u0441\u0447\u0438\u0442\u0430\u0442\u044c\u0441\u044f \u0441 \u00ab09:30:00\u00bb.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u0430\u043a\u0435\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0434\u043b\u044f \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043b\u0438\u0441\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441 &lt;evet_time> \u043c\u0435\u0436\u0434\u0443 \u00ab09:30:10 \u2013 09:30:20\u00bb.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8eb\/d91\/a33\/8ebd91a3307830fddd5d7fd31aefc2db.png\" width=\"767\" height=\"231\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8eb\/d91\/a33\/8ebd91a3307830fddd5d7fd31aefc2db.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043b\u044f \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0439 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b withWatermark() \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u043c \u0432 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0435 \u0440\u0430\u0437\u043c\u0435\u0440 \u0438\u0441\u043a\u0430\u0436\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 &lt;event_time> c \u00ab-10\u00bb \u0434\u043e \u00ab-30\u00bb, \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0432 <code>withWatermark(\"event_time\", \"10 seconds\")<\/code><\/p>\n<p><code>ts = time.time() + randint(-30, 0)<\/code><\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u043d\u043e\u0432\u043e. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0431\u044b\u043b\u0438 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0432\u043e\u0442 \u0442\u0430\u043a\u0438\u0435 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u044b:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e47\/df7\/be3\/e47df7be3004bdeb0dd14221aca9d43d.png\" width=\"686\" height=\"525\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e47\/df7\/be3\/e47df7be3004bdeb0dd14221aca9d43d.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041e\u0434\u0438\u043d \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0431\u044b\u043b \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d (16:46:10 \u2013 16:46-20), \u0430 \u00a0\u0434\u043b\u044f \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043f\u0430\u043a\u0435\u0442\u0430 \u0431\u044b\u043b\u043e \u0443\u0447\u0442\u0435\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435. <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/df0\/d5a\/06a\/df0d5a06a57feee106e63ccbf302cd1f.png\" width=\"956\" height=\"481\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/df0\/d5a\/06a\/df0d5a06a57feee106e63ccbf302cd1f.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0421\u043c\u043e\u0442\u0440\u0438\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435: \u0432 \u043b\u043e\u0433\u0430\u0445 producer\u2019\u0430 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e &lt;event_time> \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0431\u044b\u043b\u0438 \u043a\u0430\u043a \u0431\u0443\u0434\u0442\u043e \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0440\u0430\u043d\u044c\u0448\u0435, \u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u044b \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u043f\u043e\u0437\u0436\u0435 \u044d\u0442\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 (\u0431\u043e\u043b\u0435\u0435 10 \u0441\u0435\u043a\u0443\u043d\u0434). \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0438 \u0434\u043b\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \u00ab16:46:09\u00bb. Spark, \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044f &lt;event_time> \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u043c, \u0441\u0447\u0451\u043b \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437 \u043d\u0438\u0445 \u0437\u0430\u043f\u043e\u0437\u0434\u0430\u0432\u0448\u0438\u043c\u0438.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u043a\u043d\u0443 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0441\u043a\u043e\u043b\u044c\u0436\u0435\u043d\u0438\u044f \u0432 5 \u0441\u0435\u043a\u0443\u043d\u0434 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0431\u0443\u0434\u0443\u0442 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<pre><code class=\"python\">query = adViewsDF.select(from_json(col(\"value\"), schemaAdViews).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .withWatermark(\"event_time\", \"10 seconds\") \\             .groupBy(\"country\", window(\"event_time\", \"10 seconds\", \"5 seconds\").alias(\"timewindow\")) \\             .agg(count(\"*\").alias(\"count\"),                  min(\"viewing_duration\").alias(\"min\"),                  max(\"viewing_duration\").alias(\"max\"),                  sum(\"viewing_duration\").alias(\"sum\"),                  avg(\"viewing_duration\").alias(\"avg\")) \\             .writeStream \\             .format(\"console\") \\             .option(\"truncate\", \"false\") \\             .outputMode(\"append\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<p>\u041f\u0430\u043a\u0435\u0442\u044b \u0441\u0442\u0430\u043b\u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0447\u0430\u0449\u0435 \u0437\u0430 \u0441\u0447\u0451\u0442 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u0432. \u041a\u0430\u0436\u0434\u044b\u0439 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0432\u043c\u0435\u0449\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0442 \u0432\u043e \u0432\u0442\u043e\u0440\u044b\u0435 5 \u0441\u0435\u043a\u0443\u043d\u0434 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u043f\u0435\u0440\u0438\u043e\u0434\u0430.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0fa\/b6e\/ca0\/0fab6eca021368a32c3faf8df1d15375.png\" width=\"682\" height=\"662\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/0fa\/b6e\/ca0\/0fab6eca021368a32c3faf8df1d15375.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0410\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0432\u044b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u0438 \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0438 \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0438\u0445 \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0434\u0430\u043b\u0435\u0435 \u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a\u0438. <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 json \u0441 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043f\u043e \u0441\u0442\u0440\u0430\u043d\u0430\u043c.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_5_3)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_5_3\" kafka_servers = \"localhost:9092\" topic = \"adViews\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql.types import *  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_5_3\")         .getOrCreate())  adViewsDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",topic) \\             .option(\"startingOffsets\", \"latest\") \\             .option(\"failOnDataLoss\", \"false\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   schemaAdViews = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  query = adViewsDF.select(from_json(col(\"value\"), schemaAdViews).alias(\"t\")) \\             .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\             .withWatermark(\"event_time\", \"10 seconds\") \\             .groupBy(\"country\", window(\"event_time\", \"10 seconds\", \"5 seconds\").alias(\"timewindow\")) \\             .agg(count(\"*\").alias(\"count\"),                  min(\"viewing_duration\").alias(\"min\"),                  max(\"viewing_duration\").alias(\"max\"),                  sum(\"viewing_duration\").alias(\"sum\"),                  avg(\"viewing_duration\").alias(\"avg\")) \\             .writeStream \\             .format(\"json\") \\             .partitionBy(\"country\") \\             .option(\"path\", \".\/results\/ex_5_3\") \\             .option(\"checkpointLocation\", checkpoint_path) \\             .start() \\             .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p><strong>\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0434\u0432\u0443\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 (Stream \u2013 Stream join)<\/strong><\/p>\n<p>\u0418 \u0432\u043e\u0442, \u043c\u044b \u043f\u043e\u0434\u043e\u0448\u043b\u0438 \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c\u0443 \u2013 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044e\/\u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0434\u0432\u0443\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432. \u0412 \u043f\u0440\u0438\u043d\u044f\u0442\u044b\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u2013 \u0432 \u043f\u043e\u0442\u043e\u043a\u0430\u0445 \u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430\u0445 \u0438 \u043e \u043a\u043b\u0438\u043a\u0430\u0445 \u043f\u043e \u0440\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u043c \u0431\u043b\u043e\u043a\u0430\u043c \u2013 \u043d\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e id-\u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e \u0432\u0442\u043e\u0440\u0438\u0447\u043d\u044b\u043c \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u0430\u043c, \u043d\u043e \u044d\u0442\u043e \u0434\u0430\u0436\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435. \u0414\u043b\u044f join\u2019\u0430 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0430 \u0440\u0430\u0432\u0435\u043d\u0441\u0442\u0432\u043e id-\u0440\u0435\u043a\u043b\u0430\u043c\u044b, \u0441\u0442\u0440\u0430\u043d\u0443, \u0441\u0430\u0439\u0442, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0435\u0440\u0438\u043e\u0434 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043a\u043b\u0438\u043a\u0438, \u0441\u043e\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0435 \u0440\u0430\u043d\u0435\u0435 \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0440\u0435\u043a\u043b\u0430\u043c\u044b, \u044f\u0432\u043d\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u0430\u043d\u043e\u043c\u0430\u043b\u044c\u043d\u043e \u0438 \u043e\u043d\u0438 \u043d\u0430\u043c \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b. \u0423\u0441\u043b\u043e\u0432\u0438\u0435\u043c \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043a\u043b\u0438\u043a\u0430 \u0432 \u043f\u0435\u0440\u0438\u043e\u0434 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0440\u0435\u043a\u043b\u0430\u043c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c 15 \u0441\u0435\u043a\u0443\u043d\u0434 \u2013 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0440\u0435\u043a\u043b\u0430\u043c\u044b. <\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0442\u0430\u043a, \u0447\u0442\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u044c \u0441 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439, \u0442\u043e \u043f\u0440\u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 StreamDataFram\u2019\u043e\u0432 \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440 Watermark(). \u0414\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u043e\u0432 \u044d\u0442\u043e 10 \u0441\u0435\u043a\u0443\u043d\u0434, \u0430 \u0434\u043b\u044f \u043a\u043b\u0438\u043a\u043e\u0432 \u2013 20, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0435 \u0443\u043a\u0430\u0437\u0430\u043d \u0442\u0430\u043a\u043e\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0433\u043e \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u044f. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043a\u043b\u0438\u043a\u0435, \u0447\u0442\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u0435\u0439 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438. \u0414\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435, \u0443\u0432\u0438\u0434\u0435\u0432 \u0440\u0435\u043a\u043b\u0430\u043c\u0443. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0436\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u044d\u0442\u043e\u0442 \u0441\u043a\u0440\u0438\u043f\u0442.<\/p>\n<p>\u0414\u0436\u043e\u0439\u043d\u0438\u043c \u0434\u0432\u0430 \u043f\u043e\u0442\u043e\u043a\u0430:<\/p>\n<pre><code class=\"python\">query = adViewsStream.join(adClicksStream,                      expr(\"\"\"                          click_ad_id = ad_id                          AND click_site = site                         AND click_contry = country                         AND click_time >= event_time                         AND click_time &lt;= event_time + interval 15 seconds                         \"\"\"                     )                  ) \\                 .select(\"event_time\", \"click_time\", \"ad_id\", \"site\", \"country\", \"viewing_duration\") \\                 .writeStream \\                 .format(\"console\") \\                 .outputMode(\"append\") \\                 .option(\"checkpointLocation\", checkpoint_path) \\                 .start() \\                 .awaitTermination()<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_6_1)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_6_1\" kafka_servers = \"localhost:9092\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql.types import *  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_6_1\")         .getOrCreate())  adViewsDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",\"adViews\") \\             .option(\"startingOffsets\", \"latest\") \\             .option(\"failOnDataLoss\", \"false\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   schemaAdViews = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  adViewsStream = adViewsDF.select(from_json(col(\"value\"), schemaAdViews).alias(\"t\")) \\                 .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\                 .withWatermark(\"event_time\", \"10 seconds\")   adClicksDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",\"adClicks\") \\             .option(\"startingOffsets\", \"latest\") \\             .option(\"failOnDataLoss\", \"false\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")  schemaAdClicks = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True)   ])  adClicksStream = adClicksDF.select(from_json(col(\"value\"), schemaAdClicks).alias(\"t\")) \\                 .select(col(\"t.event_time\").alias(\"click_time\"), col(\"t.ad_id\").alias(\"click_ad_id\"),                          col(\"t.country\").alias(\"click_contry\"), col(\"t.site\").alias(\"click_site\")) \\                 .withWatermark(\"click_time\", \"10 seconds\")    query = adViewsStream.join(adClicksStream,                      expr(\"\"\"                          click_ad_id = ad_id                          AND click_site = site                         AND click_contry = country                         AND click_time >= event_time                         AND click_time &lt;= event_time + interval 15 seconds                         \"\"\"                     )                  ) \\                 .select(\"event_time\", \"click_time\", \"ad_id\", \"site\", \"country\", \"viewing_duration\") \\                 .writeStream \\                 .format(\"console\") \\                 .outputMode(\"append\") \\                 .option(\"checkpointLocation\", checkpoint_path) \\                 .start() \\                 .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0432 \u0441\u043a\u0440\u0438\u043f\u0442 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043c\u0435\u0442\u043d\u043e, \u0447\u0442\u043e \u043d\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0430\u043a\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u2013 \u043e\u043d\u043e \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e. \u041d\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u0430, \u0447\u0442\u043e \u043f\u0440\u0438\u0448\u0451\u043b \u0441 \u0441\u043e\u0435\u0434\u0438\u043d\u0451\u043d\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438. <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/022\/57b\/6e3\/02257b6e348a8b6e19e9b8f44fd1f2db.png\" width=\"606\" height=\"122\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/022\/57b\/6e3\/02257b6e348a8b6e19e9b8f44fd1f2db.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0418\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u00ab\u043d\u0435\u0434\u0430\u0432\u043d\u043e\u00bb \u0431\u044b\u043b\u043e \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043e \u043f\u0430\u0440\u0443 \u043a\u043b\u0438\u043a\u043e\u0432 \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u043e\u0432 \u0440\u0435\u043a\u043b\u0430\u043c\u044b \u043d\u0430 \u0441\u0430\u0439\u0442\u0435. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u044d\u0442\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0441 \u043b\u043e\u0433\u0430\u043c\u0438 \u043e\u0442 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u2013 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043b\u0438 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u0435 join\u2019\u0430.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/464\/9dd\/227\/4649dd2274b3a9af4f79459a2ac103dd.png\" width=\"806\" height=\"567\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/464\/9dd\/227\/4649dd2274b3a9af4f79459a2ac103dd.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043e \u044f\u043a\u043e\u0431\u044b \u0442\u0440\u0438 \u043a\u043b\u0438\u043a\u0430 \u043f\u043e \u0440\u0435\u043a\u043b\u0430\u043c\u0435. \u041d\u043e \u043f\u0435\u0440\u0432\u044b\u0439 \u0431\u043b\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u0440\u0435\u0447\u0438\u0442 \u0443\u0441\u043b\u043e\u0432\u0438\u044e, \u0442\u0430\u043a \u043a\u0430\u043a \u043a\u043b\u0438\u043a \u0431\u044b\u043b \u0440\u0430\u043d\u044c\u0448\u0435 \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0440\u0435\u043a\u043b\u0430\u043c\u044b, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044d\u0442\u0443 \u0441\u0442\u0440\u043e\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u043b\u043e.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043b\u0435\u0432\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u00ableftOuter\u00bb, \u0442\u043e\u0433\u0434\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430\u0445 \u0438 \u0438\u043d\u043e\u0433\u0434\u0430 \u2013 \u0435\u0449\u0451 \u0438 \u0432\u0440\u0435\u043c\u044f \u043a\u043b\u0438\u043a\u0430.<\/p>\n<pre><code class=\"python\">query = adViewsStream.join(adClicksStream,                      expr(\"\"\"                          click_ad_id = ad_id                          AND click_site = site                         AND click_contry = country                         AND click_time >= event_time                         AND click_time &lt;= event_time + interval 15 seconds                         \"\"\"                     ),                      \"leftOuter\"                  ) \\                 .select(\"event_time\", \"click_time\", \"ad_id\", \"site\", \"country\", \"viewing_duration\") \\                 .writeStream \\                 .format(\"console\") \\                 .outputMode(\"append\") \\                 .option(\"checkpointLocation\", checkpoint_path) \\                 .start() \\                 .awaitTermination()<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/391\/e00\/0d9\/391e000d9ed1f7dc3e6a3210b74ea833.png\" width=\"600\" height=\"200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/391\/e00\/0d9\/391e000d9ed1f7dc3e6a3210b74ea833.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u042d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u0430\u043b\u0435\u0435 \u0442\u0430\u043a \u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u0442\u043e\u043f\u0438\u043a Kafka.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 (ex_6_3)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import os  os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.spark:spark-streaming-kafka-0-10_2.12:3.1.1,org.apache.spark:spark-sql-kafka-0-10_2.12:3.1.1 pyspark-shell'  checkpoint_path = \".\/checkpoint\/ex_6_3\" kafka_servers = \"localhost:9092\"  import findspark findspark.init('\/home\/andrey\/spark-3.1.1-bin-hadoop3.2')  from pyspark.sql import SparkSession from pyspark.sql.functions import * from pyspark.sql.types import *  spark = (SparkSession         .builder         .appName(\"consumer_structured_streaming_ex_6_3\")         .getOrCreate())  adViewsDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",\"adViews\") \\             .option(\"startingOffsets\", \"latest\") \\             .option(\"failOnDataLoss\", \"false\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")   schemaAdViews = StructType([ \\     StructField(\"event_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True), \\     StructField(\"viewing_duration\", IntegerType(), True) \\   ])  adViewsStream = adViewsDF.select(from_json(col(\"value\"), schemaAdViews).alias(\"t\")) \\                 .select(\"t.event_time\", \"t.ad_id\", \"t.country\", \"t.site\", \"t.viewing_duration\") \\                 .withWatermark(\"event_time\", \"10 seconds\")   adClicksDF = spark \\             .readStream \\             .format(\"kafka\") \\             .option(\"kafka.bootstrap.servers\", kafka_servers) \\             .option(\"subscribe\",\"adClicks\") \\             .option(\"startingOffsets\", \"latest\") \\             .option(\"failOnDataLoss\", \"false\") \\             .load() \\             .selectExpr(\"CAST(value AS STRING)\")  schemaAdClicks = StructType([ \\     StructField(\"click_time\", TimestampType(), True), \\     StructField(\"ad_id\", IntegerType(), True), \\     StructField(\"country\", StringType(), True), \\     StructField(\"site\", StringType(), True)   ])  adClicksStream = adClicksDF.select(from_json(col(\"value\"), schemaAdClicks).alias(\"t\")) \\                 .select(\"t.click_time\", col(\"t.ad_id\").alias(\"click_ad_id\"),                          col(\"t.country\").alias(\"click_contry\"), col(\"t.site\").alias(\"click_site\")) \\                 .withWatermark(\"click_time\", \"20 seconds\")    query = adViewsStream.join(adClicksStream,                      expr(\"\"\"                          click_ad_id = ad_id                          AND click_site = site                         AND click_contry = country                         AND click_time >= event_time                         AND click_time &lt;= event_time + interval 15 seconds                         \"\"\"                     )                  ) \\                 .select(to_json(struct(\"event_time\", \"click_time\", \"ad_id\", \"site\", \"country\", \"viewing_duration\")).alias(\"value\")) \\                 .writeStream \\                 .format(\"kafka\") \\                 .option(\"kafka.bootstrap.servers\", kafka_servers) \\                 .option(\"topic\",\"adStatistic\") \\                 .option(\"checkpointLocation\", checkpoint_path) \\                 .start() \\                 .awaitTermination()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u043c\u043e\u0436\u043d\u043e, \u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0442\u044c \u0441\u0440\u0435\u0434\u043d\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0440\u0435\u0430\u043a\u0446\u0438\u0438 \u0438\u043b\u0438 \u0432 \u0440\u0430\u0437\u0431\u0438\u0432\u043a\u0435 \u043f\u043e \u0441\u0442\u0440\u0430\u043d\u0430\u043c, \u0441\u0430\u0439\u0442\u0430\u043c \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0441\u0443\u0442\u043e\u043a, \u0434\u0435\u043d\u044c \u043d\u0435\u0434\u0435\u043b\u0438 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Kafka \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 Structured Streaming. \u041c\u044b \u0443\u0432\u0438\u0434\u0435\u043b\u0438, \u0447\u0442\u043e \u043f\u0440\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438 \u0440\u0430\u0437\u043d\u044b\u0445 \u043d\u0430\u0431\u043e\u0440\u043e\u0432 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0447\u0430\u0441\u0442\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u0439. \u0412 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043d\u044b \u0442\u0430\u043a\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432. \u0422\u0430\u043a\u0436\u0435 \u0434\u0430\u043d\u044b \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438 \u043f\u043e \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044e \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0442\u0438\u043f\u043e\u0432\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a, \u0447\u0430\u0441\u0442\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0449\u0438\u0445 \u043f\u0440\u0438 \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u0438 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435. \u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u0448\u0438\u0440\u043e\u043a\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 Spark, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0440\u0435\u0448\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0441\u0430\u043c\u044b\u0445 \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/neoflex\/blog\/686242\/\"> https:\/\/habr.com\/ru\/company\/neoflex\/blog\/686242\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"bordered full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0442\u0435\u043c, \u0447\u044c\u044f \u0434\u0435\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0432\u044f\u0437\u0430\u043d\u0430 \u0441 Data Engineering, \u0438 \u0442\u0435\u043c, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u0441\u044f \u0441 \u044d\u0442\u043e\u0439 \u0441\u043b\u0430\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u0435\u0439. \u0412\u044b \u0443\u0437\u043d\u0430\u0435\u0442\u0435 \u043f\u0440\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 Kafka \u0441\u043e Structured Streaming, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0443\u0432\u0438\u0434\u0438\u0442\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0432\u043e\u0434\u044f\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043a\u0430\u043c\u0438 \u0438 \u0441\u043a\u043e\u043b\u044c\u0437\u044f\u0449\u0438\u043c \u043e\u043a\u043d\u043e\u043c.<\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u043d\u0434\u0440\u0435\u0439, \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0434\u0430\u0442\u0430-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u043c \u0438 \u043f\u043e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0443 \u0442\u0438\u043c\u043b\u0438\u0434\u043e\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438\u0437 \u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a\u043e\u0433\u043e \u0441\u0435\u043a\u0442\u043e\u0440\u0430. \u0417\u0430 \u043f\u043b\u0435\u0447\u0430\u043c\u0438 \u0443 \u043c\u0435\u043d\u044f \u0438 \u043c\u043e\u0438\u0445 \u043a\u043e\u043b\u043b\u0435\u0433 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043a\u0430\u0441\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f DWH \u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 ETL-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432. \u041d\u0430\u043c \u0432\u0441\u0435\u043c \u0441\u0442\u0430\u043b\u0438 \u0443\u0436\u0435 \u00ab\u0440\u043e\u0434\u043d\u044b\u043c\u0438\u00bb \u0442\u0430\u043a\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u043a\u0430\u043a: Oracle, PostgreSQL, GreenPlum, Hive, Impala, YARN, Spark \u0438 Airflow (\u0438 \u043f\u0440\u043e\u0447\u0438\u0435 \u0431\u0438\u0433\u0434\u0430\u0442\u0430-\u043f\u043e\u043a\u0435\u043c\u043e\u043d\u044b), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u043b\u0438\u0441\u044c \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u043f\u0430\u043a\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445. \u0410 \u0432\u043e\u0442 \u0441 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u043c\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430\u043c\u0438 \u043d\u0430 \u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u043b\u043e\u0442\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0435\u0449\u0451 \u043d\u0435 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u043b\u043e\u0441\u044c. \u041d\u0430\u0448\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u044f\u043b\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u00ab\u043f\u043e\u0434 \u043a\u043b\u044e\u0447\u00bb \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0442\u0438\u043f\u0430 \u00abReal Time Marketing\u00bb \u2013 \u0432 \u043e\u043d\u043b\u0430\u0439\u043d \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c \u0438 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0431\u0430\u043d\u043a\u0435, \u0441\u0432\u0435\u0440\u044f\u0442\u044c\u0441\u044f \u0438 \u0434\u0436\u043e\u0439\u043d\u0438\u0442\u044c\u0441\u044f \u0441 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445, \u0447\u0442\u043e\u0431\u044b \u0432 \u0438\u0442\u043e\u0433\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0438 \u0432\u044b\u0433\u043e\u0434\u043d\u044b\u0435 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u0412 \u0445\u043e\u0434\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043c\u044b \u0432\u044b\u043d\u0435\u0441\u043b\u0438 \u043c\u043d\u043e\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u0434\u043b\u044f \u0441\u0435\u0431\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u0437\u0430\u0434\u0430\u0447\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0439\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0435\u0433\u043e \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u2013 \u0432\u0435\u0441\u044c\u043c\u0430 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0441\u0442\u0440\u0438\u043c\u0438\u043d\u0433\u043e\u0432\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041d\u043e\u0432\u044b\u043c \u0431\u044b\u043b\u043e \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f, \u0442\u0430\u043a \u0438 \u0441\u0430\u043c\u0438 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438. \u041e\u0434\u043d\u0438\u043c\u0438 \u0438\u0437 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043e\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c Kafka \u0438 Spark Structured Streaming \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 Python, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u043d\u0430\u0431\u0438\u0442\u044b\u043c\u0438 \u0448\u0438\u0448\u043a\u0430\u043c\u0438 \u0438 \u0443\u043c\u043e\u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u043a\u0430\u0441\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u044d\u0442\u0438\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0438\u0445 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c. \u0423\u0432\u0435\u0440\u0435\u043d, \u0434\u043b\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0445 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0438 \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442 \u043c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u043d\u0435\u0440\u0432\u043e\u0432. \u0412\u0435\u0434\u044c \u0432\u0440\u0435\u043c\u044f, \u043a\u0430\u043a \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u0441\u0430\u043c\u044b\u0439 \u0446\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u0441\u0443\u0440\u0441.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043d\u0430\u0447\u043d\u0443 \u0441 \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u041f\u0435\u0440\u0432\u043e\u0435, \u0441 \u0447\u0435\u043c \u043c\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u2013 \u044d\u0442\u043e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0432\u0435\u0440\u0441\u0438\u044f\u0445 Hadoop \u0438 Spark, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0431\u0430\u043d\u043a\u043e\u043c \u043d\u0430 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435. \u0411\u0435\u0437\u0443\u0441\u043b\u043e\u0432\u043d\u043e, \u043c\u044b \u0434\u0430\u043b\u0438 \u0441\u0432\u043e\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438, \u043d\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0441\u043b\u043e\u0432\u043e \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u0437\u0430 \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a\u043e\u043c. \u0411\u044b\u043b\u043e \u0434\u0432\u0430 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430: Spark 2.x \u0438 Spark 3.x. \u0412\u0434\u043e\u0431\u0430\u0432\u043e\u043a \u043a \u044d\u0442\u043e\u043c\u0443, \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0440\u0430\u043d\u0435\u0435 \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u043e\u0434\u0440\u044f\u0434\u0447\u0438\u043a\u043e\u043c \u0443\u0436\u0435 \u0431\u044b\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0436\u0435\u043b\u0430\u0435\u043c\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 RDD-\u0434\u0438\u0430\u043b\u0435\u043a\u0442\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0431\u0443\u0434\u0443 \u043e\u0442\u043a\u0440\u043e\u0432\u0435\u043d\u0435\u043d \u2013 \u0432\u0435\u0441\u044c\u043c\u0430 \u043d\u0435\u0434\u0440\u0443\u0436\u0435\u043b\u044e\u0431\u0435\u043d \u0441\u0432\u043e\u0438\u043c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u043e\u043c, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u043e\u0441\u043b\u0435 \u00ab\u0432\u0430\u043d\u0438\u043b\u044c\u043d\u043e\u0433\u043e\u00bb Spark SQL. \u041d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u043e\u0440\u043e\u043c \u0435\u0449\u0451 \u043d\u0435 \u0431\u044b\u043b\u043e \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0435\u0448\u0435\u043d\u043e, \u0432 \u043a\u0430\u043a\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 Spark \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u0432 \u043a\u0430\u043a\u043e\u0439 \u043c\u0430\u043d\u0435\u0440\u0435 \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442 \u043f\u0438\u0441\u0430\u0442\u044c. <\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b:<\/p>\n<ol>\n<li>\n<p>Kafka 2.X + Spark 3.x \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u0441 Kafka + Hadoop 3;<\/p>\n<\/li>\n<li>\n<p> Kafka 2.X + Spark 2.4 + \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u0441 Kafka + Hadoop 2 \u0438\u043b\u0438 3;<\/p>\n<\/li>\n<li>\n<p> Kafka 2.X + Spark 2.x \u043d\u0435 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u0441 Kafka  + Hadoop 2;<\/p>\n<\/li>\n<li>\n<p> Kafka 2.X + Spark 2.x \u0438\u043b\u0438 Spark 3.x, \u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043d\u0430\u0434\u043e \u0432 RDD-\u043c\u0430\u043d\u0435\u0440\u0435 (\u0447\u0442\u043e \u0434\u043e\u0441\u0442\u043e\u0439\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438);<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0435\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438 \u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441 \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a\u043e\u043c \u043c\u044b \u0441\u043e\u0448\u043b\u0438\u0441\u044c, \u0447\u0442\u043e \u043d\u0430\u0434\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c Spark \u043d\u0435 \u043d\u0438\u0436\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 2.4, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 Structured Streaming \u0438 Kafka. \u0422\u043e \u0435\u0441\u0442\u044c \u0441 Kafka \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u0430\u043a \u0441\u043e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c \u0442\u0438\u043f\u043e\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0438 \u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a\u0430. <\/p>\n<p>\u041f\u0430\u0440\u0443 \u0447\u0430\u0441\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u043e\u0432 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u0434\u0430\u043b\u0438 \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 Kafka \u0447\u0435\u0440\u0435\u0437 Spark \u0435\u0441\u0442\u044c, \u043d\u043e \u043e\u043d\u0430 \u043e\u0447\u0435\u043d\u044c \u0440\u0430\u0437\u0440\u043e\u0437\u043d\u0435\u043d\u043d\u0430. \u0421\u0442\u0430\u043b\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u043c, \u0447\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0451 \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0443\u0436\u0435 \u0431\u044b\u043b\u0430 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0431\u0443\u0434\u0443\u0449\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432 \u0431\u044b\u043b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0434\u0435\u043c\u043e-\u0441\u0442\u0435\u043d\u0434 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432. <\/p>\n<p>\u0418\u0437 \u0434\u0436\u0435\u043d\u0442\u0435\u043b\u044c\u043c\u0435\u043d\u0441\u043a\u0438\u0445 \u0441\u043e\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043c\u0435\u0440\u0447\u0435\u0441\u043a\u043e\u0439 \u0442\u0430\u0439\u043d\u044b \u0438 \u0441\u043f\u0430\u0441\u0435\u043d\u0438\u044f \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f \u043e\u0442 \u043b\u0438\u0448\u043d\u0435\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u2013 \u0441\u0435\u0440\u0432\u0438\u0441 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0440\u0435\u043a\u043b\u0430\u043c\u044b. \u041d\u0430 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 Spark \u044d\u0442\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043e\u0442\u0440\u0430\u0437\u0438\u0442\u0441\u044f \u0438 \u0431\u0443\u0434\u0435\u0442 \u0434\u0430\u0436\u0435 \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u0435\u0439. \u041f\u043e\u043c\u0438\u043c\u043e \u044d\u0442\u043e\u0433\u043e, \u0445\u043e\u0440\u043e\u0448\u0438\u043c\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0433\u0443\u0442 \u0441\u043b\u0443\u0436\u0438\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u0431\u0438\u0440\u0436 (\u043a\u0440\u0438\u043f\u0442\u043e\u0431\u0438\u0440\u0436) \u0438\u043b\u0438 \u0432\u0441\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0434\u0430\u0442\u0447\u0438\u043a\u0438 \u043d\u0430 \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u044f\u0442\u0438\u0438 \u0438 \u0432 \u043e\u0444\u0438\u0441\u0435.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u043d\u0430\u0447\u0430\u043b\u0438 \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u00ab\u043e\u043a\u0435\u0430\u043d\u00bb Big Data-\u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0439, \u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0437\u043d\u0430\u0442\u044c \u2013 \u0447\u0442\u043e \u0438\u0437 \u0441\u0435\u0431\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 Kafka, Spark \u0438 \u0447\u0435\u043c \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u044c\u043d\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f Spark Streaming \u0438 Structured Streaming. \u0422\u0435\u0445, \u043a\u043e\u043c\u0443 \u044d\u0442\u0438 \u0441\u043b\u043e\u0432\u0430 \u0443\u0436\u0435 \u0445\u043e\u0440\u043e\u0448\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u044b, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u0435\u0451 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u0440\u0430\u0442\u043a\u043e \u043e Spark<\/summary>\n<div class=\"spoiler__content\">\n<p>Spark \u2013 \u044d\u0442\u043e \u043d\u0430\u0443\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0437\u0430\u0440\u043e\u0434\u0438\u0432\u0448\u0438\u0439\u0441\u044f \u0432 \u043a\u0430\u043b\u0438\u0444\u043e\u0440\u043d\u0438\u0439\u0441\u043a\u043e\u043c \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442\u0435 \u0432 2009 \u0438 \u0441\u0442\u0430\u0432\u0448\u0438\u0439 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445. \u0415\u0433\u043e \u0433\u043b\u0430\u0432\u043d\u044b\u043c \u0430\u0432\u0442\u043e\u0440\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0443\u043c\u044b\u043d\u043e-\u043a\u0430\u043d\u0430\u0434\u0441\u043a\u0438\u0439 \u0443\u0447\u0451\u043d\u044b\u0439 \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u043a\u0438 \u041c\u0430\u0442\u0435\u0439 \u0417\u0430\u0445\u0430\u0440\u0438\u044f (Matei Zaharia).\u00a0Spark \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0431\u044b\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 Scala \u0438 \u0437\u0430\u0442\u0435\u043c \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043d \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Java. \u0414\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0440\u044d\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043a\u0430\u043a \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445, \u0442\u0430\u043a \u0438 \u0441\u043b\u0430\u0431\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u041f\u043e\u043c\u0438\u043c\u043e \u0440\u043e\u0434\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432 Scala, Java, \u0430 \u0442\u0430\u043a\u0436\u0435 R, \u0434\u0430\u043d\u043d\u044b\u0439 \u0444\u0440\u044d\u0439\u043c\u0432\u043e\u0440\u043a \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0438 \u0432 Python-\u0441\u043a\u0440\u0438\u043f\u0442\u0430\u0445. \u00a0<\/p>\n<p>Spark \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c\u0438 \u0438 \u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a\u0430\u043c\u0438: \u0431\u0443\u0434\u044c \u0442\u043e \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 (PostgreSQL, Oracle), NoSQL (Cassandra, MongoDB), \u0444\u0430\u0439\u043b\u044b \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 (csv, json, parquet) \u0438\u043b\u0438 \u0442\u043e\u043f\u0438\u043a\u0438 Kafka. \u0412\u0434\u043e\u0431\u0430\u0432\u043e\u043a \u043a \u044d\u0442\u043e\u043c\u0443 \u0432 Spark \u0435\u0441\u0442\u044c 4 \u043c\u043e\u0434\u0443\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0442 \u0436\u0438\u0437\u043d\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u0430\u0442\u0430-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0443, \u043d\u043e \u0438 \u0434\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0442\u0438\u0441\u0442\u0443:<\/p>\n<ul>\n<li>\n<p>SQL \u2013 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c SQL-\u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430\u0434 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445;<\/p>\n<\/li>\n<li>\n<p>Streaming \u2013 \u043c\u043e\u0434\u0443\u043b\u044c \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0434\u0443\u043b\u044e \u043f\u043e \u0441\u0443\u0442\u0438 \u0438 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u0441\u0442\u0430\u0442\u044c\u044f;<\/p>\n<\/li>\n<li>\n<p>MLlib \u2013 \u043d\u0430\u0431\u043e\u0440 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u043c\u0430\u0448\u0438\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>GraphX \u2013 \u043c\u043e\u0434\u0443\u043b\u044c \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0433\u0440\u0430\u0444\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0434\u043d\u043e\u0439 \u0438\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0438\u0434\u0435\u043e\u043b\u043e\u0433\u0438\u0439 Spark \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u043e\u0435 \u043f\u043e\u043d\u044f\u0442\u0438\u0435 \u043a\u0430\u043a \u00ab\u043b\u0435\u043d\u0438\u0432\u044b\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f\u00bb (lazy evaluation). \u0422\u043e \u0435\u0441\u0442\u044c \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u0434 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043d\u0430\u0447\u043d\u0443\u0442\u0441\u044f \u043d\u0435 \u0441\u0440\u0430\u0437\u0443, \u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 Spark \u0443\u0432\u0438\u0434\u0438\u0442 \u0432 \u0441\u0432\u043e\u0451\u043c \u043f\u043b\u0430\u043d\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u2013 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0415\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u0435\u0433\u043e \u0438\u0434\u0435\u043e\u043b\u043e\u0433\u0438\u0435\u0439 (\u0438\u043b\u0438 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e) \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u2013 \u043d\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043a \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f\u043c, \u0430 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043a \u0434\u0430\u043d\u043d\u044b\u043c. \u042d\u0442\u043e\u0442 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430 HDFS \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435, \u0433\u0434\u0435 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0444\u0430\u0439\u043b, \u043f\u043e\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0438 \u0440\u0435\u043f\u043b\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u0435\u0439, \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u043d\u043e\u0434\u0430\u0445 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430. Spark \u0441\u0430\u043c \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 (\u0442\u0440\u0430\u043d\u0441\u043b\u0438\u0440\u0443\u0435\u0442) \u043a\u043e\u0434-\u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u043f\u043e \u0432\u0441\u0435\u043c \u0443\u0437\u043b\u0430\u043c \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430, \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u0442 \u0435\u0433\u043e \u043d\u0430 \u043f\u043e\u0434\u0437\u0430\u0434\u0430\u0447\u0438, \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043f\u043b\u0430\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u0412\u0441\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0442 \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438. \u041d\u0438\u0436\u0435 \u2013 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0438\u0447\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u044b \u0440\u0430\u0431\u043e\u0442\u044b Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<figure class=\"full-width\"><figcaption>\u0421\u0445\u0435\u043c\u0430 \u0440\u0430\u0431\u043e\u0442\u044b Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f <\/figcaption><\/figure>\n<p>\u041f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0432\u044b\u043c \u0447\u0435\u0440\u0435\u0437 SparkSession (\u0432 \u0440\u0430\u043d\u043d\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 SparkContext) \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u043e\u0440, \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 Driver, \u043e\u043d \u043e\u0431\u0449\u0430\u0435\u0442\u0441\u044f \u0441\u043e \u0432\u0441\u0435\u043c\u0438 Worker\u2019\u0430\u043c\u0438 (\u0440\u0430\u0431\u043e\u0447\u0438\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430), \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 (RAM \u0438 CPU). \u041a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u0443\u0437\u0435\u043b \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 Executor\u2019\u043e\u0432 (\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0435\u0439), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0437\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 Task\u2019\u0430 (\u0417\u0430\u0434\u0430\u0447\u0438) \u2013 \u043d\u0430\u0438\u043c\u0435\u043d\u044c\u0448\u0430\u044f \u0435\u0434\u0438\u043d\u0438\u0446\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430, \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0435 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u043f\u043e\u0440\u0446\u0438\u0435\u0439 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 \u0440\u0430\u0437\u0434\u0435\u043b\u0443 RDD. \u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 Driver\u2019\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0451 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044f\u0445. RDD (Resilient Distributed Dataset) \u2013 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u044f, \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u0430\u044f, \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u0430\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u0445\u0440\u0430\u043d\u044f\u0449\u0438\u0445\u0441\u044f \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<p>\u041d\u0430\u0434\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e Spark \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043d\u0430 \u043c\u0435\u0441\u0442\u0435 \u2013 \u0435\u0433\u043e \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0430\u044e\u0442 \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u044e\u0442. \u0414\u043e Spark 1.6 \u0431\u044b\u043b \u0442\u043e\u043b\u044c\u043a\u043e RDD API \u0441 \u043d\u0435 \u0441\u0430\u043c\u043e\u0439 \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u043c\u0430\u043d\u0435\u0440\u043e\u0439 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0439, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u2013\u00a0\u0432 \u043c\u0430\u043d\u0435\u0440\u0435 MapReduce. \u041f\u043e\u0442\u043e\u043c \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u0442\u0430\u043a\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043a\u0430\u043a Dataframe \u0438 Dataset, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043a\u0430\u043a c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439, \u0445\u0440\u0430\u043d\u044f\u0449\u0435\u0439\u0441\u044f \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438. \u0422\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0441\u0442\u0430\u043b\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0432 SQL-\u043c\u0430\u043d\u0435\u0440\u0435 (\u0443\u0440\u0430!).\u00a0 <\/p>\n<p>\u0412 Spark 2.0 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f SparkSession, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0442\u0430\u043b \u0435\u0434\u0438\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u0432\u0445\u043e\u0434\u0430 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0438 \u0434\u0430\u043d\u043d\u044b\u0445 Spark. \u0422\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u043e\u043d \u0437\u0430\u043c\u0435\u043d\u0438\u043b \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a SparkContext, SQLContext, HiveContext, SparkConf \u0438 StreamingContext (\u0445\u043e\u0442\u044f \u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442 \u0438\u0445 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c).<\/p>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u0432\u0435\u0440\u0441\u0438\u0438 2.4, Kafka \u0441\u0442\u0430\u043b \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0434\u0443\u043b\u044f Structured Streaming. \u0412 3 \u0432\u0435\u0440\u0441\u0438\u0438 Spark \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0438<br \/>\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438: \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0435\u043d SQL-\u0434\u0432\u0438\u0436\u043e\u043a,<br \/>\u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a Python \u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 PySpark, \u043e\u0431\u0440\u0435\u0437\u043a\u0430 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0445<br \/>\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 \u0438 \u043c\u043d\u043e\u0433\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435. \u041a\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b \u0432\u0441\u0435 \u043d\u043e\u0432\u043e\u0432\u0432\u0435\u0434\u0435\u043d\u0438\u044f Spark 3.0, \u0442\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441\u043e \u0441\u0442\u0430\u0442\u044c\u0451\u0439: <a href=\"https:\/\/databricks.com\/session_na20\/deep-dive-into-the-new-features-of-apache-spark-3-0\">https:\/\/databricks.com\/session_na20\/deep-dive-into-the-new-features-of-apache-spark-3-0<\/a><\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 Spark Structured Streaming<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 Structured Streaming \u0431\u044b\u043b\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0432 Spark 2.0 \u0432 2016 \u0433\u043e\u0434\u0443 \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Apache Spark \u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430. \u0421 \u0432\u0435\u0440\u0441\u0438\u0438 Spark 2.2 \u043e\u043d \u0431\u044b\u043b \u043f\u0440\u0438\u0437\u043d\u0430\u043d \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u043c, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 Structured Streaming \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 \u0444\u0440\u0435\u0439\u043c\u043e\u0432\u0440\u043a\u0435 Spark, \u0430 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044e DStreams \u2013 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u043c. <\/p>\n<p>Structured Streaming, \u0442\u0430\u043a \u0436\u0435 \u043a\u0430\u043a \u0438 \u0435\u0433\u043e \u043f\u0440\u0435\u0434\u0448\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0438\u043a Spark Streaming, \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u043c\u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445: TCP-\u0441\u043e\u043a\u0435\u0442\u044b, \u0444\u0430\u0439\u043b\u044b (\u0438\u0437 HDFS, S3, \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0424\u0421), Kafka, AWS Kinesis \u0438 \u043f\u043e\u043c\u0438\u043c\u043e \u044d\u0442\u043e\u0433\u043e SQL \u0438 NoSQL \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u043c SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u043d\u0430 \u043c\u043e\u0434\u0443\u043b\u0435 Spark SQL \u0438 API \u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 \u2013 Dataframe \u0438 Dataset, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u043c\u0438 \u0432 \u044f\u0437\u044b\u043a\u0430\u0445 Java, Scala, Python \u0438 R.<\/p>\n<p>\u0423\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u0439 Spark Streaming (\u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 DStream) \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442 RDD API \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 \u043c\u0438\u043a\u0440\u043e\u043f\u0430\u043a\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e\u0442\u043e\u043a\u0430, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0430\u044f \u0441\u0435\u0440\u0438\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0437\u0430\u0434\u0430\u043d\u0438\u0439 \u043f\u0430\u043a\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 \u0441\u0442\u0438\u043b\u0435 map\/reduce. <\/p>\n<figure class=\"full-width\"><figcaption>\u041f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b Spark DStream<\/figcaption><\/figure>\n<p>\u0412 \u043d\u043e\u0432\u043e\u043c Structured Streaming\u2019\u0435 \u0431\u044b\u043b\u043e \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0430 \u0435\u0434\u0438\u043d\u0430\u044f \u0443\u043d\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043f\u0430\u043a\u0435\u0442\u043d\u043e\u0439 \u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u043e\u0442\u043e\u0439\u0434\u044f \u043e\u0442 RDD API. \u041f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0430\u043b \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u0430\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0430.   <\/p>\n<figure class=\"full-width\"><figcaption>\u041c\u043e\u0434\u0435\u043b\u044c \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 Structured Streaming <\/figcaption><\/figure>\n<p>\u0412 Structured Streaming \u0435\u0441\u0442\u044c \u0442\u0440\u0438 \u0440\u0435\u0436\u0438\u043c\u0430 \u0432\u044b\u0432\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p><strong>Append mode<br \/><\/strong>\u0422\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u043a \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0441 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430, \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0432\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435. \u042d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 (\u0432 DataFram\u0435) \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c\u0441\u044f;<\/p>\n<\/li>\n<li>\n<p><strong>Update mode<\/strong><br \/>\u0412\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0431\u0443\u0434\u0443\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u0441\u0442\u0440\u043e\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0441<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-337956","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/337956","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=337956"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/337956\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=337956"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=337956"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=337956"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}