Slide 1

Slide 1 text

Apache KafkaʹΑΔ εέʔϥϒϧ ΞϓϦέʔγϣϯ։ൃ yuuki takezawa 
 PHP Conference 2017

Slide 2

Slide 2 text

͸͡Ίʹ • ن໛ಁաੑ
 ෛՙͷߴ௿ʹ߹ΘͤͯϦ
 ιʔεɾϓʔϧΛ֦େɾॖখͰ͖Δ͜ͱ • Ґஔಁաੑ
 Ϣʔβʔ΍Ϧιʔε͕ͲΕ͚ͩ཭Ε͍ͯΔ͔ҙࣝͤͣʹɺ มΘΒͳ͍࢖͍উखͰγεςϜ͕ར༻Ͱ͖Δ͜ͱ • ҟछಁաੑ
 γεςϜΛߏ੒͢Δػث΍ιϑτ΢ΣΞ͕ҟͳ͍ͬͯΔ͜ ͱΛҙࣝͤͣʹ؅ཧɾར༻Ͱ͖Δ͜ͱ

Slide 3

Slide 3 text

Agenda • Message Queue • What is Apache Kafka? • For PHP

Slide 4

Slide 4 text

Message Queue

Slide 5

Slide 5 text

ίϝϯτ౤ߘαʔϏε • ϩάΠϯϢʔβʔ͸ίϝϯτ͕౤ߘͰ͖Δ • ະϩάΠϯϢʔβʔ͸ӾཡͷΈ͕Ͱ͖Δ • ͓ؾʹೖΓͨ͠ϢʔβʔͷίϝϯτΛӾཡͰ͖Δ • ࣌ܥྻͰίϝϯτΛӾཡͰ͖Δ • ίϝϯτͷ࡟আ͕Ͱ͖Δ • ίϝϯτͷฤू͸Ͱ͖ͳ͍ ͳͲ

Slide 6

Slide 6 text

ΞϓϦέʔγϣϯ࣮૷ • ೝূػೳͷ࣮૷ • ίϝϯτ౤ߘɺฤूɺӾཡػೳ࣮૷ • ݕࡧػೳͷ࣮૷ • ਺ਓͷ։ൃऀ

Slide 7

Slide 7 text

γϯϓϧͳΞϓϦέʔγϣϯߏ੒

Slide 8

Slide 8 text

γϯϓϧͳΞϓϦέʔγϣϯߏ੒ public function __invoke(Comment $comment) { $query = $comment->query(); $query->insert(['title', 'body']) ->values([ 'title' => 'First post', 'body' => 'Some body text', 'id' => $this->auth->getId(), ]) ->execute(); }

Slide 9

Slide 9 text

ෳࡶԽ͢ΔΞϓϦέʔγϣϯ • ػೳ௥Ճ
 • ίϝϯτ৘ใΛଞͷػೳͰར༻͍ͨ͠
 • ৚݅ʹΑΔҰཡ৘ใͷιʔτมߋ
 Ϣʔβʔ৘ใଐੑʹΑΔιʔτॱมߋ

Slide 10

Slide 10 text

ෳࡶԽ͢ΔΞϓϦέʔγϣϯ

Slide 11

Slide 11 text

ෳࡶԽ͢ΔΞϓϦέʔγϣϯ public function __invoke(Comment $comment, Movie $movie) { $query = $comment->query(); $commentId = $query->insert(['title', 'body', 'comment_id']) ->values([ 'title' => 'First post', 'body' => 'Some body text', 'comment_id' => $this->auth->getId(), ]) ->execute(); $movieQuery = $movie->query(); $movieQuery->insert(['movie_id', 'comment_id']) ->values([ 'movie_id' => $movie->getId(), 'comment_id' => $commentId, ]) ->execute(); }

Slide 12

Slide 12 text

Ϗδωεͷ੒௕ͱͱ΋ʹ ංେԽ͢ΔΞϓϦέʔγϣϯ

Slide 13

Slide 13 text

ංେԽ͢ΔΞϓϦέʔγϣϯ • ऩӹԽͷͨΊͷػೳ
 • རศੑͷͨΊͷػೳ • طଘػೳͷ֦ு

Slide 14

Slide 14 text

ංେԽ͢ΔΞϓϦέʔγϣϯ

Slide 15

Slide 15 text

ංେԽ͢ΔΞϓϦέʔγϣϯ public function __invoke( Comment $comment, Movie $movie, Follow $follow, Company $company ) { $movieCommentId = false; if ($follow->isFollow()) { $query = $comment->query(); $commentId = $query->insert(['title', 'body', 'comment_id']) ->values([ 'title' => 'First post', 'body' => 'Some body text', 'comment_id' => $this->auth->getId(), ]) ->execute(); $movieQuery = $movie->query(); $movieCommentId = $movieQuery->insert(['movie_id', 'comment_id']) ->values([ 'movie_id' => $movie->getId(), 'comment_id' => $commentId, ]) ->execute(); } if ($movie->isCompany() && $movieCommentId) { $company->appendMovie($movie->getId()); // ϝʔϧૹ৴ } }

Slide 16

Slide 16 text

ΞϓϦέʔγϣϯͷΫϥεͦͷ΋ͷΛ ίϯϙʔωϯτԽ ґଘੑΛऔΓআ͘

Slide 17

Slide 17 text

ΞϓϦέʔγϣϯɾσʔλϕʔεϦϑΝΫλϦϯά • ݁߹ͨ͠ػೳΛίϯϙʔωϯτఏڙ
 • APIʹΑΔσʔλૢ࡞ͷந৅Խ
 • σʔλϕʔεύϑΥʔϚϯεվળ


Slide 18

Slide 18 text

ΞϓϦέʔγϣϯɾσʔλϕʔεϦϑΝΫλϦϯά

Slide 19

Slide 19 text

ڊେͳΞϓϦέʔγϣϯ΁ • αʔϏε֦େʹͱ΋ͳ͏ΞϓϦέʔγϣϯ௥Ճ
 • ґଘίϯϙʔωϯτ૿Ճ
 -> ࢓༷มߋٵऩ • ૿Ճ͢ΔAPIར༻
 -> ᷓΕग़͢ଞαʔϏεͷϏδωεϩδοΫ • σʔλϕʔε໰୊
 -> ElasticsearchɺSolrͳͲͷಋೖ

Slide 20

Slide 20 text

ڊେͳΞϓϦέʔγϣϯ΁

Slide 21

Slide 21 text

ਂࠁͳ໰୊ • ࢓༷มߋʹ൐͏ίϯϙʔωϯτमਖ਼ͱϦϦʔεෳࡶԽ
 ϥΠϒϥϦͷόʔδϣϯ͋͛ͳ͖Όɾɾʂ
 ͋ͷػೳΛऔΓࠐΉʹ͸͋Εͱ͜Εͱɾɾɾ • ΞϓϦέʔγϣϯؒ࿈ܞͷෳࡶԽ
 APIमਖ਼ʹ൐͏Өڹൣғௐࠪ
 վमͯ͠΋࢖ͬͯ͘Εͳ͍໰୊

Slide 22

Slide 22 text

ਂࠁͳ໰୊ • σʔλಉظͷෳࡶԽ
 ϦΞϧλΠϜͰσʔλ͕ཉ͍͠
 ΠϯσοΫεߋ৽͕ఆظ࣮ߦ
 • ͦͷଞ
 Ͳ͔͜ͷαʔϏε͕मਖ਼͞ΕͨΒো֐ʹ
 • ෳࡶԽ͢Δ࣮૷ίʔυ

Slide 23

Slide 23 text

੒௕͍ͯ͘͠ࣄۀʹ߹Θͤͯɺ ΞϓϦέʔγϣϯΛ Ͳ͏εέʔϧ͍͔ͤͯ͘͞

Slide 24

Slide 24 text

มΘΓΏ͘؀ڥ • σʔλΛऔಘ͢Δʹ͸ʁ
 APIίʔϧʹΑΔ౎౓֬ೝʁ
 Ωϟογϡ͸Կ෼ʁ
 • ͦΕͧΕͷαʔϏεͰͦΕͧΕͷݴޠ΁
 ͋ΔαʔϏε͸PHPɺ͋ΔαʔϏεͰ͸Go ScalaͳͲ
 ϥΠϒϥϦ͕ෛͷҨ࢈Խ


Slide 25

Slide 25 text

σʔλॲཧ Ϣʔβʔ৘ใ͸౎౓໰͍߹Θͤ ৘ใΛߋ৽ͨ͠৔߹Ͱ΋
 ґଘαʔϏε͕ͳ͍ͨΊ໰୊ͳ͠

Slide 26

Slide 26 text

σʔλॲཧͷෳࡶԽ Ϣʔβʔ৘ใมߋ Ϣʔβʔ৘ใ࡟আ Ϣʔβʔ৘ใ͕ݟ͔ͭΒͳ͍ͨΊ
 σʔλॲཧ͝ͱʹ"1*ΞΫηε ͋ͦ͜ͱͦ͜Ͱ৘ใ͕ҧ͏ʂ
 Ͳͷσʔλ͕ຊ෺ʁ શͯͷΞϓϦέʔγϣϯ͔Β
 Ωϟογϡͳ͠ͰΞΫηε
 ৗʹߴෛՙঢ়ଶʹ

Slide 27

Slide 27 text

Command and Query Responsibility Segregation (CQRS)

Slide 28

Slide 28 text

CQRS • ॻ͖ࠐΈʢCommandʣͱಡग़͠ʢQueryʣͷ
 ੹຿Λ෼཭͢Δઃܭ
 • ͋ΒΏΔϝιου͸ɺΞΫγϣϯΛ࣮ߦ͢ΔίϚϯυ͔ɺݺͼ ग़͠ݩʹσʔλΛฦ͢ΫΤϦ͔ͷ͍ͣΕ͔Ͱ͋ͬͯɺ྆ํΛ ߦͬͯ͸ͳΒͳ͍ɻ͜Ε͸ɺ࣭໰Λ͢Δ͜ͱͰճ౴ΛมԽͤ͞ ͯ͸ͳΒͳ͍ͱ͍͏͜ͱͩɻ
 
 "Greg YoungྲྀCQRS - Mark Nijhof". Digital Romanticism. 
 http://d.hatena.ne.jp/digitalsoul/20100712/1278886009 ࢀর 


Slide 29

Slide 29 text

CQRS "A few myths about CQRS". Ouarzy's Blog. 
 http://www.ouarzy.com/2016/10/02/a-few-myths-about-cqrs/ ࢀর

Slide 30

Slide 30 text

CQRS • σʔλϕʔεૢ࡞ΛಡΈࠐΈɺॻ͖ࠐΈͱ෼཭
 • RDBMSΛ׆͔͢
 ਖ਼نԽɾτϥϯβΫγϣϯ
 • αʔϏεʹ߹ΘͤͨϞσϦϯά
 RDBMS·ͨ͸Elasticsearch/SolrͰฦ٫ͳͲ
 • Event Sourcingͱ૊Έ߹ΘͤΔ

Slide 31

Slide 31 text

CQRSͱEvent Sourcing σʔλϕʔεߋ৽
 $PNNBOE σʔλϕʔεߋ৽׬ྃΠϕϯτ
 &WFOU4PVSDJOH σʔλϕʔεߋ৽׬ྃݕ஌
 &WFOU-JTUFOFS Ωϟογϡ࡟আͳͲ

Slide 32

Slide 32 text

ϑϨʔϜϫʔΫʹΈΔQueue • LaravelͰ͸͕͔͔࣌ؒΔॲཧ΍ඇಉظॲཧΉ͚ʹɺ
 QueueίϯϙʔωϯτΛఏڙ • QueueΛར༻͢ΔͨΊʹRedis΍RDBMSɺ
 ·ͨ͸υϥΠό֦ுͰ೚ҙͷϛυϧ΢ΣΞ͕ར༻Մೳ • ղܾʁ
 LaravelͷQueueΛଞݴޠؒɾαʔϏεؒͰ࢖͏͜ͱ͸ ೉͍͠(php serializeͳͲ͕͞Ε͍ͯΔ)

Slide 33

Slide 33 text

What is Apache Kafka?

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

ϝοηʔδϯάγεςϜ

Slide 36

Slide 36 text

ଟ༷ͳ෼ࢄܕϝοηʔδϯάϛυϧ΢ΣΞ • Redis (PubSub) • ZeroMQ • RabbitMQ • Apache Kafka

Slide 37

Slide 37 text

Redis • KVSͷҰػೳɺPubSub(SUBSCRIBE, PUBLISHίϚϯυ) • Redis SentinelΛར༻ͯ͠ϑΣΠϧΦʔόʔΛߦ͏ • LPUSHͳͲΛར༻ͯ͠ϝοηʔδΛอ؅ ͳͲ • ϝοηʔδ࠶औಘ΍τϥϯβΫγϣϯػೳ͸ͳ͍ • ϨϓϦέʔγϣϯՄ

Slide 38

Slide 38 text

ZeroMQ • ϛυϧ΢ΣΞͰ͸ͳ͘ɺϥΠϒϥϦ • ΞϓϦέʔγϣϯ͕ؒ௨৴Λߦ͍ɺϝοηʔδॲཧ • ϛυϧ΢ΣΞΛར༻͠ͳ͍ͨΊߴ଎ • ϝοηʔδͷӬଓԽػೳ͸ແ͍ҝɺ
 ಠࣗͰ࣮૷͢Δඞཁ͕͋Δ

Slide 39

Slide 39 text

RabbitMQ • Advanced Message Queuing Protocol(AMQP) • ΤϯλʔϓϥΠζΞϓϦέʔγϣϯͰଟ਺ར༻࣮੷ • ϝοηʔδͷӬଓԽɺϨϓϦέʔγϣϯՄೳ • τϥϯβΫγϣϯΛར༻࣮ͯ֬͠ʹॲཧΛߦ͏ • v3.6.0Ͱ௥Ճ͞ΕͨLazy QueuesͰେ༰ྔͷσʔλ஝ੵՄ • ϑΣΠϧΦʔόʔ

Slide 40

Slide 40 text

Apache Kafka • ZookeeperΛར༻ͨ͠ΫϥελϦϯάʹΑΔߴՄ༻ੑ • ϝοηʔδͷӬଓԽɺϨϓϦέʔγϣϯɺ࠶औಘՄ • ϏοάσʔλରԠ • ϑΝΠϧγεςϜར༻Ͱɺ
 γʔέϯγϟϧΞΫηεʹΑΔߴ଎Խ • ετϦʔϜରԠͷϝοηʔδϯάϛυϧ΢ΣΞ • Kafka ConnectʹΑΔपลγεςϜͱͷߴ͍਌࿨ੑ
 (Amazon kinesisͱ΄΅ಉ͡)

Slide 41

Slide 41 text

Apache Kafka֓ཁ • Producer 
 ϝοηʔδ഑৴Λߦ͏
 ֤ݴޠͷΫϥΠΞϯτϥΠϒϥϦΛར༻ • Consumer 
 ϝοηʔδߪಡΛߦ͏
 ফඅ͞Εͨϝοηʔδ͸ഁغ͞Εͣɺ
 Ұఆظؒอ؅͞ΕΔ • Broker
 KafkaຊମͰɺProducerɺConsumerؒͷΩϡʔ

Slide 42

Slide 42 text

Apache ZooKeeper֓ཁ • ઃఆ؅ཧ΍ɺ໊લղܾͳͲΛߦ͏
 ෼ࢄίʔσΟωʔγϣϯΤϯδϯ • ෳ਺୆Ͱߏ੒͢ΔZooKeeperͷ͏ͪ1୆͕ɺ
 ͢΂ͯͷॻ͖ࠐΈΛௐఀɾडཧ͢ΔϦʔμʔ • Ϋϥελͷ͏ͪա൒਺͕ಈ࡞͢Δঢ়ଶʹ͢Δ͜ͱ͕ඞ ཁͰ͋ΔͨΊɺح਺୆Ͱߏ੒͢Δ͜ͱ͕ඞཁ

Slide 43

Slide 43 text

Apache Kafka + ZooKeeper Architecture

Slide 44

Slide 44 text

Apache Kafka֓ཁ • Topic 
 Producer͔Βͷϝοηʔδ͸͜ͷTopicʹ֨ೲ͞ΕΔ
 ϝοηʔδ͸Ұҙʹ؅ཧɺFIFO(ޙड़partition)Ͱॲཧ • Partition
 ෛՙ෼ࢄ༻్ʹར༻
 ෳ਺ͷConsumer͕ͦΕͧΕͷPartitionΛࢀর͠ɺ
 ͦΕͧΕ͕ॲཧΛߦ͏
 ॲཧϑϩʔͷσβΠϯʹΑͬͯଟ༷ͳར༻ํ๏

Slide 45

Slide 45 text

Example Partition

Slide 46

Slide 46 text

Kafka Connect • Kafka Connectͱ͸ɺ
 पลγεςϜ͔ΒͷσʔλΛऔΓࠐΈ(Source)ɺ
 σʔλૹ৴(Sink)ͷೋछྨΛαϙʔτ͢Δػೳ • Amazon SQS΍MongoDBͷσʔλΛKafkaͰऔࠐΉɺ
 ϝοηʔδΛͦͷ··Elasticsearch΍RDBMSʹ֨ೲɺ
 ͕ߦ͑Δ • Connect͸ࣗ༝ʹ֦ுͯ͠ಠࣗConnectΛ࣮૷Մೳ
 (java, Scala)

Slide 47

Slide 47 text

Example Kafka Connect &WFOU4PVSDJOH ଞΞϓϦέʔγϣϯ
 $POTVNFS ૹ৴಺༰Λͦͷ··
 &MBTUJDTFBSDI΁

Slide 48

Slide 48 text

Kafka Streams • KafkaͰετϦʔϜॲཧΛ࣮૷͢Δػೳ • ͋ΔτϐοΫʹσʔλ͕֨ೲ͞ΕΔ࣌ʹ
 Կ͔ॲཧΛ࣮ߦ͠ଞͷτϐοΫʹ֨ೲ͢Δ • Consumerͳ͠Ͱ্هͷॲཧΛ࣮ݱ • ௚ۙ30෼ʹ͓͚ΔPVϥϯΩϯάɺ
 ϝοηʔδ಺ͷจࣈྻมߋɺ௥ՃͳͲ

Slide 49

Slide 49 text

ϝοηʔδͷܽଛ ૹ৴ࣦഊ BDLड৴ࣦഊ #SPLFSμ΢ϯ ϝοηʔδड৴ࣦഊ

Slide 50

Slide 50 text

Exactly Once • 0.11͔Β௥Ճ • Producer, BrokerؒͷτϥϯβΫγϣϯ
 Broker, ConsumerؒͷτϥϯβΫγϣϯ • ਖ਼֬ʹҰ౓͚ͩૹ৴

Slide 51

Slide 51 text

ϝοηʔδ఻ୡͷอূ • At least once semantics
 ॏෳΛڐՄ • At most once semantics
 ܽଛΛڐՄ • Exactly once semantics
 ॏෳɺ͓ΑͼܽଛΛڐՄ͠ͳ͍
 
 "Exactly-once Semantics are Possible: Here’s How Kafka Does it". Confluent APACHE KAFKA. 
 https://www.confluent.io/blog/exactly-once-semantics-are-possible-heres-how-apache-kafka-does-it/ ࢀর

Slide 52

Slide 52 text

KSQL • Kafkaʹอ؅͞Ε͍ͯΔϝοηʔδʹ
 SQLΠϯλʔϑΣʔεͰΞΫηε͢Δ΋ͷ • ݱࡏDeveloper Preview • RESTͰΞΫηε͢Δ͜ͱ͕Ͱ͖·͢

Slide 53

Slide 53 text

KappaΞʔΩςΫνϟ

Slide 54

Slide 54 text

KappaΞʔΩςΫνϟ

Slide 55

Slide 55 text

Apache Kafka࠾༻ • ෼ੳॲཧΛ࣮૷͢Δʹ͋ͨΓɺStreamରԠ͕༰қͳࣄ • Kafka ConnectʹΑΔσʔλετϨʔδͱͷ࿈ܞ • Facebook Prestoͱͷ࿈ܞ͕؆୯
 (RDBMS౳ͱ݁߹ͯ͠σʔλఏڙ͕Մೳ) • ґଘ෼ղͷͨΊʹεέʔϧ͢Δ
 ϝοηʔδϯάγεςϜߏங͕༰қ • ϝοηʔδ࠶औಘͱো֐ରԠ͕༰қͰ͋Δࣄ • PHPΤΫεςϯγϣϯ͕͋Δ(rdkafka)

Slide 56

Slide 56 text

Architecture

Slide 57

Slide 57 text

Kafka client for PHP

Slide 58

Slide 58 text

Rdkafka https://github.com/arnaud-lb/ php-rdkafka

Slide 59

Slide 59 text

Rdkafka • librdkafka(C/C++)ΛPHPͰར༻Մೳʹͨ͠
 ΤΫεςϯγϣϯ • High Level API & Row Level API • PHP5/7ରԠ • librdkafkaͱkafkaͷઃఆΛཧղ͢Δ͜ͱ

Slide 60

Slide 60 text

Rdkafka Producer࣮૷ $rk = new RdKafka\Producer(); $rk->setLogLevel(LOG_DEBUG); $rk->addBrokers(“127.0.0.1"); $topic = $rk->newTopic("test"); $topic->produce( RD_KAFKA_PARTITION_UA, 0, json_encode(['message' => ‘phpcon']) );

Slide 61

Slide 61 text

Rdkafka Producer࣮૷ $rk = new RdKafka\Producer(); $rk->setLogLevel(LOG_DEBUG); $rk->addBrokers(“127.0.0.1"); $topic = $rk->newTopic("test"); $topic->produce( RD_KAFKA_PARTITION_UA, 0, json_encode(['message' => ‘phpcon']) ); $MVTUFSͷ৔߹͸ɺ
 ΧϯϚ۠੾ΓͰࢦఆ

Slide 62

Slide 62 text

Rdkafka Producer࣮૷ $rk = new RdKafka\Producer(); $rk->setLogLevel(LOG_DEBUG); $rk->addBrokers(“127.0.0.1"); $topic = $rk->newTopic("test"); $topic->produce( RD_KAFKA_PARTITION_UA, 0, json_encode(['message' => ‘phpcon']) ); $MVTUFSͷ৔߹͸ɺ
 ΧϯϚ۠੾ΓͰࢦఆ 5PQJD໊ 1BSUJUJPOΛࢦఆ

Slide 63

Slide 63 text

Rdkafka Consumer࣮૷ $conf = new RdKafka\Conf(); $conf->set('group.id', 'myConsumerGroup'); $rk = new RdKafka\Consumer($conf); $rk->addBrokers("127.0.0.1"); $topicConf = new RdKafka\TopicConf(); $topicConf->set('auto.commit.interval.ms', 100); $topicConf->set('offset.store.method', 'file'); $topicConf->set( 'offset.store.path', sys_get_temp_dir() ); $topicConf->set('auto.offset.reset', 'smallest');

Slide 64

Slide 64 text

Rdkafka Consumer࣮૷ $conf = new RdKafka\Conf(); $conf->set('group.id', 'myConsumerGroup'); $rk = new RdKafka\Consumer($conf); $rk->addBrokers("127.0.0.1"); $topicConf = new RdKafka\TopicConf(); $topicConf->set('auto.commit.interval.ms', 100); $topicConf->set('offset.store.method', 'file'); $topicConf->set( 'offset.store.path', sys_get_temp_dir() ); $topicConf->set('auto.offset.reset', 'smallest'); ฒྻͰಉ͡UPQJDΛಉ࣌ʹ ॲཧ͢Δ৔߹͸ಉ໊͡લʹ

Slide 65

Slide 65 text

Rdkafka Consumer࣮૷ $conf = new RdKafka\Conf(); $conf->set('group.id', 'myConsumerGroup'); $rk = new RdKafka\Consumer($conf); $rk->addBrokers("127.0.0.1"); $topicConf = new RdKafka\TopicConf(); $topicConf->set('auto.commit.interval.ms', 100); $topicConf->set('offset.store.method', 'file'); $topicConf->set( 'offset.store.path', sys_get_temp_dir() ); $topicConf->set('auto.offset.reset', 'smallest'); ฒྻͰಉ͡UPQJDΛಉ࣌ʹ ॲཧ͢Δ৔߹͸ಉ໊͡લʹ $POTVNFSઃఆ஋Λࢦఆ

Slide 66

Slide 66 text

Rdkafka Consumer࣮૷ $topic = $rk->newTopic("test", $topicConf); $topic->consumeStart(0, RD_KAFKA_OFFSET_STORED); while (true) { $message = $topic->consume(0, 120*10000); switch ($message->err) { case RD_KAFKA_RESP_ERR_NO_ERROR: var_dump($message); break; case RD_KAFKA_RESP_ERR__PARTITION_EOF: echo "No more messages; will wait for more\n"; break; case RD_KAFKA_RESP_ERR__TIMED_OUT: echo "Timed out\n"; break; default: throw new \Exception($message->errstr(), $message->err); break; } }

Slide 67

Slide 67 text

Rdkafka Consumer࣮૷ $topic = $rk->newTopic("test", $topicConf); $topic->consumeStart(0, RD_KAFKA_OFFSET_STORED); while (true) { $message = $topic->consume(0, 120*10000); switch ($message->err) { case RD_KAFKA_RESP_ERR_NO_ERROR: var_dump($message); break; case RD_KAFKA_RESP_ERR__PARTITION_EOF: echo "No more messages; will wait for more\n"; break; case RD_KAFKA_RESP_ERR__TIMED_OUT: echo "Timed out\n"; break; default: throw new \Exception($message->errstr(), $message->err); break; } } Ͳͷ1BSUJUJPOΛར༻͢Δ͔
 औಘҐஔ͸Ͳ͔͜Β͔

Slide 68

Slide 68 text

Rdkafka Consumer࣮૷ $topic = $rk->newTopic("test", $topicConf); $topic->consumeStart(0, RD_KAFKA_OFFSET_STORED); while (true) { $message = $topic->consume(0, 120*10000); switch ($message->err) { case RD_KAFKA_RESP_ERR_NO_ERROR: var_dump($message); break; case RD_KAFKA_RESP_ERR__PARTITION_EOF: echo "No more messages; will wait for more\n"; break; case RD_KAFKA_RESP_ERR__TIMED_OUT: echo "Timed out\n"; break; default: throw new \Exception($message->errstr(), $message->err); break; } } Ͳͷ1BSUJUJPOΛར༻͢Δ͔
 औಘҐஔ͸Ͳ͔͜Β͔ ਖ਼ৗʹड৴ͨ͠৔߹ʹ
 ೚ҙͷॲཧΛ࣮ߦ

Slide 69

Slide 69 text

Rdkafka Consumerͷઃఆ • heartbeatͱλΠϜΞ΢τ
 heartbeat.interval.ms͸
 session.timeout.msΑΓখ͘͞ɺ1/3ΑΓେ͖͘
 • Supervisord౳Ͱϓϩηε؂ࢹ͸ඞਢ • group.idʹΑΔॲཧͷฒྻԽ
 ෳ਺ConsumerͰಉ͡idΛࢦఆ͢Δͱฒߦʹ

Slide 70

Slide 70 text

Notice • ΫϦʔϯͳ࣮૷Λ৺͕͚Δ
 Consumer͸PHPͱ͸ݶΒͳ͍
 ΫϦʔϯͳϥΠϒϥϦɺ࣮૷Λ • RdkafkaͰૹ৴͢Δ͔FluentdͳͲͰૹ৴͢Δ͔͸
 ΞϓϦέʔγϣϯ࣍ୈ • RdkafkaΛϥΠϒϥϦܦ༝ͳͲͰ͸ͳ͘ɺ
 ͦͷ··ར༻͢Δ

Slide 71

Slide 71 text

ϝοηʔδͷόϦσʔγϣϯ͸Ͳ͜Ͱʁ • ProducerͰόϦσʔγϣϯ
 -> ࠷௿ݶͷܕकΔ
 -> ଞαʔϏεͷ஌͕ࣝඞཁʹͳΔ৔߹͸࣮૷͠ͳ͍
 • ConsumerͰόϦσʔγϣϯ
 ड৴ͨ͠ϝοηʔδΛௐ΂ɺ
 ਖ਼͘͠ͳ͍΋ͷΛεΩοϓ

Slide 72

Slide 72 text

ϝοηʔδͷόϦσʔγϣϯ͸Ͳ͜Ͱʁ • Kafka Streamͱ͍͏બ୒ࢶ
 java·ͨ͸ScalaͰ࣮૷Մೳ
 -> ࣮૷ࣗମ͸ͦΜͳʹ೉͘͠ͳ͍
 • αʔϏεͷ஌ࣝ͸ઐ༻ͷStreamͰߦ͏
 -> ϚΠΫϩαʔϏεͰ͋Ε͹

Slide 73

Slide 73 text

PipelineDBͱ͍͏બ୒ࢶ • ྲྀΕͯ͘Δϝοηʔδʹରͯ͠ɺ
 ϦΞϧλΠϜʹɺSQL Likeʹऔಘ͍ͨ͠
 • ͔ͭετϨʔδΛѹഭͤͨ͘͞ͳ͍
 • PostgreSQL Compatible
 • PDOͰ઀ଓՄೳʂ

Slide 74

Slide 74 text

PipelineDBͱ͍͏બ୒ࢶ CREATE EXTENSION pipeline_kafka; SELECT pipeline_kafka.add_broker(‘localhost:9092'); CREATE STREAM logs_stream (payload json); CREATE CONTINUOUS VIEW message_count AS SELECT COUNT(*) FROM logs_stream;

Slide 75

Slide 75 text

ҰาਐΜͩ෼ࢄΞϓϦέʔγϣϯ • PrestoΛར༻͠ɺ
 RDBMS΍Redisͱ૊Έ߹Θͤͨσʔλऔಘ͕Մೳ
 RedisͷϥϯΩϯάͱRDBMSͷਖ਼نԽ͞Εͨσʔλɺ
 KafkaΛ࢖ͬͨ௚ۙͷϩάσʔλΛֻ͚߹Θͤͨ
 Ϩίϝϯυ

Slide 76

Slide 76 text

Apache Kafkaͷ࢝Ίํ • Apache Kafkaެࣜϖʔδ͔Βμ΢ϯϩʔυ • Confluent͔Βμ΢ϯϩʔυ • Kafka ConnectΛར༻͢ΔͷͰ͋Ε͹ɺ
 Confluentར༻͕Φεεϝ • Hadoop౳͕ͳͯ͘΋ར༻ՄೳͰ͢

Slide 77

Slide 77 text

Apache Kafka GUI • Cluster؅ཧ 
 https://github.com/yahoo/kafka-manager • Message؅ཧ 
 https://github.com/landoop/kafka-topics-ui
 https://github.com/ldaniels528/trifecta
 ͳͲ

Slide 78

Slide 78 text

·ͱΊ • ෳࡶԽͨ͠ΞϓϦέʔγϣϯɾ෼ࢄΞϓϦέʔγϣϯ ͷ໰୊ղܾͷҰͭ • KafkaҎ֎ͷMessage Queue΋બ୒ࢶʹ • StreamॲཧͳͲ͕ඞཁͰ͋Ε͹KafkaΛਪ঑ • ن໛ʹ͋Θͤͨϛυϧ΢ΣΞબఆɾো֐ରԠɾӡ༻Λ