事業の成長と、それにともなうアプリケーションの課題、 発生しがちな問題を追いながら、 解決策の一つであるCQRS導入について解説します。 分散システムで発生する問題についても軽く触れていきます。
ࣄۀͷεέʔϧΞτΛࢧ͑ΔPHPͰ࡞ΔࢄΞʔΩςΫνϟYuuki Takezawa / ytake
View Slide
Profile• ᖒ ༗و / ytake• ελʔϑΣεςΟόϧגࣜձࣾ• PHP, Hack, Go, Scala• Apache Hadoop, Apache Spark, Apache Kafka • twitter https://twitter.com/ex_takezawa• facebook https://www.facebook.com/yuuki.takezawa• github https://github.com/ytake
ελʔϑΣεςΟόϧגࣜձࣾ
ͦΜͳελʔϑΣεςΟόϧͰΤϯδχΞืूதʂʂʂ
Caution• ࠓճͷ༰શͯͷΞϓϦέʔγϣϯͰ ద༻Ͱ͖ΔͷͰ͋Γ·ͤΜ• ࣮ࡍʹຊਓ͕࠾༻͍ͯ͠Δͷ ϕʔεͷ༰Ͱ͢
Agenda• ΞϓϦέʔγϣϯͷͱ λʔχϯάϙΠϯτ • ղܾ͢ΔͨΊͷࣝ• ࢄτϥϯβΫγϣϯରࡦ
Ϗδωεͷͱ৫
খ͞ͳνʔϜ• σʔλϕʔεઃܭ + ORM etc ϑϨʔϜϫʔΫͰߏங͞ΕΔ ΞϓϦέʔγϣϯ • গਓͷ։ൃऀͰߏ͞ΕΔ։ൃ৫
ෳͷνʔϜ• ૿͑ΔΞϓϦέʔγϣϯػೳ • ։ൃνʔϜͷ૿һ εΩϧ༷ʑ
ΞϓϦέʔγϣϯͱσʔλϕʔε• ORMͰN+1͕૿͑Δέʔε ൃߦͨ͠SQL ΞϓϦέʔγϣϯʹ߹͍ͬͯΔ͔ʁ• ϝϞϦɺCPUͳͲͷ૿ڧͰΓΔ ͕ޙճ͠ʹͳΔ͜ͱ
ͬͯ͠·͍͕ͪͳରԠ• σʔλऔಘ؆ུԽͷͨΊͷ σʔλϕʔεઃܭ(;͑Δඇਖ਼نԽ) • ͱΓ͋͑ͣϦετͰશ෦औಘ ͦΕ͔Β1ϨίʔυͣͭৄࡉΛऔಘ͠Α͏
ΞϓϦέʔγϣϯͱσʔλϕʔε• SELECT * FROM articles; SELECT * FROM users WHERE user_id = ?; • ͜Ε͕͠10000݅औಘͰ ൃߦ͞Ε͍ͯͨΒʁ • ORM͕ѱ͍ͷͰͳ͘ దʹར༻Ͱ͖͍ͯͳ͍έʔε
େ͖͘νʔϜͱࣄۀͷ• ૿͑ଓ͚ΔΞϓϦέʔγϣϯػೳ • ։ൃνʔϜͷڊେԽ ෳͷνʔϜߏͱ ෳͷεςʔΫϗϧμ
ෆ҆ఆͳΞϓϦέʔγϣϯ• Ϩίʔυ૿Ճɾ࣮ίʔυ૿ՃʹΑΔ ͞ΒͳΔύϑΥʔϚϯεԼ• ͍͡ΊΒΕଓ͚Δσʔλϕʔε• ͋ͪͪ͜Ͱى͜Γ࢝ΊΔো
ࠔͳཁ݅ͷ࣮ݱ• ϦΫΤετ͝ͱʹϨεϙϯεΛΈཱͯ ΞϓϦέʔγϣϯͷύϑΥʔϚϯεѱԽ • ਖ਼نԽ͍͍ͨ͠ͷͷɺཁ݅ʹ߹Θͤͨσʔλऔಘίετ૿
ͬͯ͠·͍͕ͪͳରԠ• ݪҼΘ͔Γ·ͤΜ͕͘ͳ͖ͬͯͨͷͰΩϟογϡ͠·͢ -> ෳࡶԽ͢ΔΩϟογϡαʔόʔ• ݪҼΘ͔Γ·ͤΜ͕͘ͳ͖ͬͯͨͷͰΩϟογϡ͠·͢ -> ΩϟογϡαʔόʹՃ͑ͯCDNՃ
͏खஈ͕ͳ͍ɾɾɾʂ
ڊେͳΞϓϦέʔγϣϯ
σʔλॲཧͷෳࡶԽϢʔβʔใมߋ ϢʔβʔใআϢʔβʔใ͕ݟ͔ͭΒͳ͍ͨΊ σʔλॲཧ͝ͱʹ"1*ΞΫηε͋ͦ͜ͱͦ͜Ͱใ͕ҧ͏ʂ Ͳͷσʔλ͕ຊʁશͯͷΞϓϦέʔγϣϯ͔Β Ωϟογϡͳ͠ͰΞΫηε ৗʹߴෛՙঢ়ଶʹ
ࢭΊΒΕͳ͍ϏδωεͷՃ
ฐ• ϦϦʔε༏ઌͷͨΊɺ ܧ͗͠ͷΞϓϦέʔγϣϯ • εςʔΫϗϧμ૿Ճʹ͏ ΞϓϦέʔγϣϯͷෳࡶԽ• খதنͷΞϓϦέʔγϣϯ࣌ͷ ઃܭͱ࣮༝དྷͷෆ۩߹͕૿Ճ
σʔλઃܭ༝དྷͷ• େྔσʔλͷϑϧεΩϟϯ • INDEXෆͷͨΊͷύϑΥʔϚϯεԼ• γϯϓϧͳߏނͷػೳՃ࣌ͷ ΫΤϦෳࡶԽ
࣮ίʔυ༝དྷͷฐ• ػೳՃͷͨΊͷௐࠪʹ2ϲ݄ • ͞·͟·ͳཁҼͷੵΈॏͶʹΑΓ བྷΈ߹ͬͨίʔυͰϞνϕʔγϣϯμϯ• ͕͔͔࣌ؒͬͯ͠·͏͕ނɺ ϏδωενʔϜʹ·ͣҰݴ ʮ͕͔͔࣌ؒΔͷͰͰ͖·ͤΜʯ
ͦͷ݁Ռ• Ϗδωεͷػձଛࣦ• γϡϦϯΫ࢝͠ΊΔࣄۀ• ଞࣾʹෛ͚ͯ͠·͏ࣄۀ• څ༩্͕͕Βͳ͍ɾɾ
͜ΕͰࣄۀ͕εέʔϧ͠ͳ͍ʂ
ࣄۀ͢Δͷ• ΞϓϦέʔγϣϯϦϦʔε͔ͯ͠Β• ఆ֎ͷΛ͛Δ WebΞϓϦέʔγϣϯ• ͞·͟·ͳϏδωεͷՄೳੑΛߟྀͨ͠ σʔλઃܭ
Λࢧ͑Δʹʁ• ఆظతͳσʔλϕʔεϦϑΝΫλϦϯάɺΞϓϦέʔγϣϯͷϦϑΝΫλϦϯά ͕࣮ࢪͰ͖Δ͔• ͋Γͱ͋ΒΏΔՄೳੑΛఆͨ͠σʔλઃܭෆՄೳ27
ΞϓϦέʔγϣϯͰى͜Δ• ਖ਼نԽ͞Εͨςʔϒϧͱ ඇਖ਼نԽςʔϒϧͷઓ͍• ෳࡶԽ͢Δॻ͖ࠐΈॲཧͱଟൃ͢ΔN+1• σʔλϞσϧͱυϝΠϯϞσϧ͕ҟͳΔ
Α͋͘ΔN+1• Λऔಘ͠ ҬɾΩονϯใΛऔಘ • ΠΠωɺΫνίϛऔಘ͠ͳ͚Ε...
public function run(): \Generator{foreach ($repository->findAll() as $row){yield new ReadProductTransfer($row,$this->kitchenRepository->find($row->getId()),$this->areaRepository->find($row->getId())); } }
͜Μͳςʔϒϧઃܭͨ͠هԱ͋Γ·ͤΜ͔ʁ• UIΛߏ͢Δཁૉ͕औಘ͍͢͠ ςʔϒϧઃܭ• JOIN͢Δͱ͘ͳΔʁ ͳΒϫΠυΧϥϜઃܭͩ
͜Μͳςʔϒϧ͋Γ·ͤΜ͔ʁ• ͳʹ͔ͷεςʔλεΛฦ͢ʹ ͋ͷΧϥϜͱ͜ͷΧϥϜͱ͋ΕΛɾɾɾɻ• ϏδωεϩδοΫ͕ςʔϒϧʹ͋Δ• ΧϥϜ໊ͱ༻్͕શ͘ผ
ΞϓϦέʔγϣϯͰى͜Δ• ඇਖ਼نԽςʔϒϧಛఆͷཁ݅ͰղܾͰ͖Δ͕ɺͦΕҎ֎ʹ͍͠ɻ σʔλநग़ܥɺ αʔϏε֦େɺ༷มߋͳͲʹແཧ͕͋Δ
ཁ݅ͱσʔλߏͷࠩඞͣ͋Δ
ॻ͖ࠐΈͱಡΈࠐΈͷҧ͍ॻ͖ࠐΈ ಡΈࠐΈҰ؏ੑɾՄ༻ੑτϥϯβΫγϣϯΛ༻͍ͯॻ͖ࠐΈΛߦ͏Ұ؏ੑॏࢹ݁Ռ߹ੑͱՄ༻ੑσʔλ ਖ਼نԽ ඇਖ਼نԽεέʔϥϏϦςΟҰൠతʹεέʔϥϏϦςΟ ॏཁͰͳ͍ଟ͘ൺॏΛΊ͓ͯΓ εέʔϥϏϦςΟॏཁ
ߟ͑ΔϙΠϯτ• ॻ͖ࠐΈॲཧͰɺಡΈࠐΈཁ݅ʹରԠ͢ΔͨΊͷॲཧ͕ଟ͍• ಡΈࠐΈཁ݅ΛΒͳ͚Εॻ͖ࠐΊͳ͍• Ϩεϙϯεͱσʔλߏ͕͋·Γʹҧ͍͗͢Δ
ߟ͑ΔϙΠϯτ• σʔλͷਖ਼͠͞ͱཁ݅Ϩϕϧͷਖ਼͠͞ҧ͏ͷ• ͲͪΒ͔ʹدͤͨઃܭʹ͢Δɺ Ͱͳ྆͘ํΛͰ͖Εγϯϓϧʹ
ϛυϧΣΞϨϕϧͰ
ॻ͖ࠐΈଟͷΞϓϦέʔγϣϯ• ॻ͖ࠐΈʹڧ͘ɺ εέʔϧ͕༰қͳσʔλϕʔε Cassandra, DynamoDB etc
ಡΈࠐΈଟͷΞϓϦέʔγϣϯ• RDBMSͷΈͰे • LIKEݕࡧͳͲElasticsearch, Solr
ղܾɺͰ͖ͳ͍ɾɾ• ϛυϧΣΞϨϕϧͰͷղܾํ๏Ͱɺ ΞϓϦέʔγϣϯࣗମ͕࣋ͭ ෳࡶ͞ղܾͰ͖ͳ͍ɻ• ύϑΥʔϚϯε໘ͰͷվળͰ͖Δ͕ɺ ࣄۀͷΛࢧ͑ΔεϐʔσΟ͞ͳ͍
ΞϓϦέʔγϣϯϨϕϧͷ՝
ΞϓϦέʔγϣϯϨϕϧͰͷ՝• ੳΛߦΘͳ͍͜ͱʹΑΔޡͬͨ൚༻Խ• ෳͷίϯςΩετ͕ࠞࡏ• ͳΜͰ͠Α͏ͱ͢Δॲཧ
ڥք͚ΒΕͨίϯςΩετ ໊ ѻ͍ͬͯΔΩονϯళฮஈ ൢചظؒͰ͢
ڥք͚ΒΕͨίϯςΩετQSPEVDU/BNF LJUDIFO/BNFQSJDFTBMFT1FSJPE
ڥք͚ΒΕͨίϯςΩετ ໊ ݸૹઌͰ͢
ڥք͚ΒΕͨίϯςΩετQSPEVDU/BNF LJUDIFO/BNFQSJDFTBMFT1FSJPERVBOUJUZTJQQJOH"EESFTT
ڥք͚ΒΕͨίϯςΩετ ໊ ஈͰ͢
ڥք͚ΒΕͨίϯςΩετ• ͱ͍͏ݴ༿Ͱ༰͕ҟͳΔ• ΞϓϦέʔγϣϯͰଟʑ• ڞ௨ԽͰ͖ΔͷͰͳ͍
ڥք͚ΒΕͨίϯςΩετ• ྫ͑ɺΛࢦ͢ݴ༿ͱ DB্ͷproductsςʔϒϧҰக͠ͳ͍έʔε͕ଟ͍ • ͲͪΒ͔ʹ߹ΘͤΒΕΔͷͰͳ͍ͱ ೝࣝ͢Δ͜ͱ
ॻ͖ࠐΈͱಡΈࠐΈΛͯ͠ΈͯͲ͏͔
CQRS
CQRS• ॻ͖ࠐΈϞσϧͱಡΈࠐΈϞσϧΛִ• υϝΠϯϞσϧͷ͚ͩͰͳ͘ σʔλετΞ͢ΒཧతʹผʹՄೳ ؔ৺ࣄͷΛపఈ • DDDʹ͓͚ΔಡΈࠐΈͱॻ͖ࠐΈͷࠩΛղܾ͢Δύλʔϯ
CQRSͳΜΒ͔ͷมॲཧΛ௨ͯ͡ 3FBEͷσʔλΛߋ৽
CQRS• CommandͱReadʹڥքઢ͕͋Δ• CommandͱRead ಉ͡ϦϙδτϦɺϢʔεέʔεͱ͠ͳ͍• ಉ͡ςʔϒϧࢀর͠ͳ͍
σʔλϕʔεͰ͖Εʁ
େ͖͘ͳͬͨαʔϏεͰղܾ͞ΕΔ• ෳࡶԽ͍ͯͨ͠ಡΈࠐΈϞσϧͷ ύϑΥʔϚϯεΛվળ• ಡΈࠐΈϞσϧʹؔ͢Δ εέʔϥϏϦςΟ্
ҙ• CQRSಛఆͷػೳʹͷΈద༻Մೳ ΞϓϦέʔγϣϯશͯʹద༻͢ΔͷͰͳ͍• ॻ͖ࠐΈϞσϧͱಡΈࠐΈϞσϧͷ͕ࠩΑ͘Θ͔Βͳ͍ -> ཁ݅ͷੳΛ·ͣ͠·͠ΐ͏
CQRSʹΑͬͯղܾ͞ΕΔ• ॻ͖ࠐΈϞσϧCUDΛ୲͠ɺ υϝΠϯϞσϧͷ࣮Λߦ͏• ಡΈࠐΈϞσϧͷ୯७Խ DTOͷΈ
CQRSʹΑͬͯղܾ͞ΕΔ• ಡΈࠐΈϞσϧɺཁ݅ʹ߹Θͤͨ ͞·͟·ͳσʔλϕʔεΛར༻͠ ಡΈࠐΈϞσϧͷύϑΥʔϚϯεΛվળ• ॻ͖ࠐΈϞσϧಉ༷ʹ ཁ݅ʹ߹ΘͤͨσʔλϕʔεΛར༻
ྫ• ϥϯΩϯάॲཧ ͋Δظؒ·ͰͷσʔλΛͬͨ ϥϯΩϯάΛੜ• ٻσʔλͷੜ ͳͲ
ϥϯΩϯά࡞• ϦΫΤετຖʹϥϯΩϯά࡞ -> εέʔϧ͠ͳ͍ • ྫ͑1ԯલޙͷશσʔλʹରͯ͠ ΫΤϦΛ͛ͯऔಘ͢Δ
ͷϥϯΩϯάྫ• ྫ͑ ͦͷͷΛѻ͏Ϟσϧͱ ϥϯΩϯάΛߏ͢ΔͷϞσϧΛ ڞ௨Խͯ͠͠·͏
ͷϥϯΩϯάྫ• ྫ͑ ͦͷͷΛѻ͏Ϟσϧͱ ϥϯΩϯάΛߏ͢ΔͷϞσϧΛ ڞ௨Խͯ͠͠·͏ -> વμϝ
ϥϯΩϯά࡞ղܾ• લ·ͰͷσʔλΛͬͯ ϥϯΩϯάΛ࡞Δཁ݅ͷ߹ ʢཁ݅ʹΑͬͯมΘΓ·͢ʣ• σʔλͷߏཁૉෆมͰ ੜ͢Δඞཁͳ͍ ࣄલʹσʔλΛੜ͠ɺϦʔυΛ୲͢Δσʔλϕʔεʹอ࣋
ϥϯΩϯά࡞ղܾ• ϥϯΩϯάʹ͍ͭͯͷ͕ࣝͳ͘ͱ ಘΒΕΔ͜ͱ͕Ͱ͖Δ• ElasticsearchͷΤΠϦΞεͳͲΛ ར༻͢Δ͜ͱͰ༰қʹରԠՄೳ
ϥϯΩϯά࡞ղܾ• ϥϯΩϯάੜʹෆ۩߹͕͋ͬͨ߹ɺ ࠶ੜ͢Εྑ͍• ো͕͋ͬͯ࠶࣮ߦ͢ΕΑ͍
CQRS ར
CQRS ར• োੑͷ্• εέʔϥϏϦςΟ• ޮͷྑ͍σʔλϕʔεͷબ• పఈͨؔ͠৺ͷ
CQRS ܽ
CQRS ܽ• ҰͭҰͭͷػೳγϯϓϧ ߏ͢Δཁૉ͕૿͑ΔͨΊશମͰݟΔͱෳࡶԽ • ϨϓϦέʔγϣϯͷλΠϜϥά
ෳࡶԽ• CUDΞϓϦέʔγϣϯ • RΞϓϦέʔγϣϯ• ಡΈࠐΈϞσϧߋ৽ΞϓϦέʔγϣϯ
ෳࡶԽ• ѻ͏σʔλϕʔε͕૿͑Εɺ ͦΕͧΕͷσʔλϕʔεʹ߹Θͤͨ ཧɺӡ༻ํ๏͕ඞཁ• ։ൃ࣌ʹෳͷσʔλϕʔεͷ͕ࣝ ඞਢ
ϨϓϦέʔγϣϯͷλΠϜϥά• γϯϓϧͳϥϯΩϯάͳͲͳ͠ • ϦΞϧλΠϜੑ͕ཁٻ͞ΕΔॲཧ ྫ) ͕ొ͞ΕͨΒଈ ݕࡧΫΤϦͰώοτͰ͖Δ༷ʹͯ͠ʂ
ϨϓϦέʔγϣϯͷλΠϜϥά• ͍͍ͶϘλϯΛԡͨ͠ΒΠϯΫϦϝϯτ/σΫϦϝϯτͤͯ͞ɺ͍͍ͶॱͰιʔτ• ϝοηʔδ͕ߘ͞ΕͨΒɺ ϑΥϩϫʔશһʹϦΞϧλΠϜͰ௨
CQRS͚ͩͰղܾ͕Ͱ͖ͳ͍• DBͷτϦΨʔͳͲΛ༻͍ͯมߋΛݕ ҟͳΔσʔλϕʔεΛબ͢Δͱ ରԠෆՄೳ• ϦʔυϞσϧߋ৽༻ϓϩηεΛ ༻ҙ͠ͳ͚ΕͳΒͳ͍ ͕ɺมߋͷݕ͕͏·͘Ͱ͖ͳ͍
ྫ֎• Debezium• DynamoDB streams• LinkedIn Databus ͳͲॻ͖ࠐΈΛݕͯ͠௨Մೳ
CQRS͚ͩͰղܾ͕Ͱ͖ͳ͍• ҟͳΔσʔλϕʔεͷίϛοτ • 2ϑΣʔζίϛοτରԠ͍ͨ͠Ί ආ͚ͳ͚ΕͳΒͳ͍
ϑϨʔϜϫʔΫͰղܾͰ͖Δ͡ΌΜʂ• ྫ͑Laravel QueueɺPHPͷΦϒδΣΫτΛ γϦΞϥΠζ͠QueueʹಥͬࠐΜͩ• पลγεςϜ͕PHPͩͱݶΒͳ͍
Event Sourcing
Event Sourcing• ΠϕϯτΛهͯ͠࠶ݱ͢Δύλʔϯ• ΠϕϯτΛΠϕϯτετΞʹอଘ͠ਅͷιʔεʹ• ه͞ΕͨΠϕϯτ͔ΒΦϒδΣΫτΛ෮ݩ• Πϕϯτෆม
Event Sourcing• ಡΈࠐΈ͕ར༻͢Δσʔλϕʔεͷ өʹඞਢ• ৴པͰ͖Δਅͷσʔλιʔεʹ ΠϕϯτετΞʹσʔλ͕͋Εྑ͍
Message Brokerબఆ• PubSubͰشൃੑͷͳ͍ͷΛબ͢Δ• ϝοηʔδอ͕ՄೳͰɺ࠶ݱ͢Δ͜ͱ͕ՄೳͳͷΛ࠾༻͢Δͷ͕·͍͠• εέʔϥϒϧͰ͋Δ͜ͱ
͓͢͢Ίʁ• Message BrokerεέʔϥϏϦςΟॏࢹ• ۙͷΠϕϯτΛ͙͢ʹऔಘͰ͖Δͷ• ۤ࿑ͨ͘͠ͳ͚ΕApache Kafka (AWS MSK / Confluent ͳͲ)
Event SourcingCQRS
CQRSσʔλߋ৽͕ൃੜʂ ৽͍͠σʔλૹΓ·͢Ͷ
ղܾͰ͖Δ
ෳࡶ͔ͭϋΠύϑΥʔϚϯεͳ ݕࡧ
N+1ͳͲʹΑΔύϑΥʔϚϯεྼԽεφοϓγϣοτతʹσʔλΛ ॻ͖ࠐΈ MBTUJOTFSU*%͕Ͳ͏͍͍ͯͨ͠߹ͳͲ
N+1ͳͲʹΑΔύϑΥʔϚϯεྼԽ%#ॻ͖ࠐΈྃޙɺಛఆͷΠϕϯτΛൃߦ
N+1ͳͲʹΑΔύϑΥʔϚϯεྼԽಡΈࠐΈϞσϧߋ৽ϓϩηε͕ΠϕϯτΛফඅ
N+1ͳͲʹΑΔύϑΥʔϚϯεྼԽ&MBTUJDTFBDIॻ͖ࠐΈ ಛఆͷϨίʔυͷΈॻ͖͑Δ ྫ͑ϥΠΫɺίϝϯτͳͲ
N+1ͳͲʹΑΔύϑΥʔϚϯεྼԽಡΈࠐΈγϯϓϧʹ ΠϯσοΫεʹ͍߹ΘͤΔͷΈ ෳࡶͳܭࢉॲཧߦΘͳ͍
ϝϦοτ• ॴҦεϚʔτUIύλʔϯΛ ଞʹӨڹΛ༩͑Δ͜ͱͳ࣮͘ݱ• ॻ͖ࠐΈͰඞཁͱ͞ΕΔਖ਼نԽΛ่͢͜ͱͳ͘ ରԠՄೳ• ಡΈࠐΈΛεέʔϧ͍ͤ͢͞
ϝϦοτ• ಡΈࠐΈϞσϧͷߋ৽ॲཧࢸͬͯ؆୯ • ߹ʹΑͬͯϏδωεϩδοΫΛ࣮͢Δ͜ͱ͋ΓɺෳࡶʹͳΒͳ͍Α͏ʹҙ͢Δ
ҙ• Ϩίʔυʹߋ৽ɺ আ͕ൃੜ͢Δ߹ μʔςΟϦʔυʹҙ
ࢄτϥϯβΫγϣϯ
ࢄτϥϯβΫγϣϯ• ಡΈࠐΈϞσϧߋ৽ϓϩηε͕ ෳͷσʔλϕʔεʹ ॻ͖ࠐ·ͳ͚Ε͍͚ͳ͍έʔε• 2ϑΣʔζίϛοτίετ͕ߴ͍
ࢄτϥϯβΫγϣϯ͘͠ɺෳࡶ• ཧతʹҟͳΔσʔλϕʔεͰ ॲཧ͕ࣦഊͨ͠߹ • औΓফ͢ॲཧΛΒͤͳ͚ΕͳΒͳ͍• NoSQLKafkaͳͲʹͳ͍
ࢄτϥϯβΫγϣϯΛΘͳ͍• ҰͭͷϓϩηεͰ ෳσʔλϕʔεॻ͖ࠐΉͷΛආ͚Δ• Ͳ͏ͯ͠ආ͚ΒΕͳ͍߹ ϚΠΫϩαʔϏεΞʔΩςΫνϟͷ τϥβΫγϣϯରࡦͷҰͭɺSagaΛར༻
ίϨΦάϥϑΟͷαʔΨडΠϕϯτΛൃߦ
ίϨΦάϥϑΟͷαʔΨΩονϯαʔϏε͕ डΠϕϯτΛফඅ1&/%*/(ঢ়ଶͱ͢Δ
ίϨΦάϥϑΟͷαʔΨΩονϯαʔϏε͕ ༻ҙΠϕϯτΛൃߦ
ίϨΦάϥϑΟͷαʔΨ༻ҙΠϕϯτΛফඅΫϨδοτܾࡁΛ࣮ߦ
ίϨΦάϥϑΟͷαʔΨձܭαʔϏε͕ ܾࡁྃΠϕϯτΛൃߦ
ίϨΦάϥϑΟͷαʔΨΩονϯαʔϏε͕ ܾࡁྃΠϕϯτΛফඅ ࠷ऴతͳΠϕϯτΛऔಘ͢Δ·Ͱ"8"*5*/(ঢ়ଶͱ͢Δ
ίϨΦάϥϑΟͷαʔΨडαʔϏε͕ ܾࡁྃΠϕϯτΛফඅ
ίϨΦάϥϑΟͷαʔΨडαʔϏε͕ डΛਖ਼ৗऴྃͱݟ၏͠௨
ίϨΦάϥϑΟͷαʔΨडਖ਼ৗऴྃΛফඅ͠ɺΦʔμʔ௨ΓͷྉཧΛ։࢝
ίϨΦάϥϑΟͷαʔΨ ϝϦοτ• ର͕গͳ͘ɺγϯϓϧͳॲཧͷϑϩʔʹ࠷ద • ॲཧͷ͕ࢄ͍ͯ͠ΔͨΊ ୯Ұোͳ͠
ίϨΦάϥϑΟͷαʔΨ σϝϦοτ• ࢄ͍ͯ͠Δ͕ނʹΘ͔Γʹ͍͘• ॥ґଘ• ݁߹ςετͷқ͕ߴ͍• ؔ͢ΔαʔϏεͷΠϕϯτશͯαϒεΫϥΠϒ͢Δඞཁ͕͋Δ
ΦʔέετϨʔγϣϯͷαʔΨडΠϕϯτΛൃߦ
ΦʔέετϨʔγϣϯͷαʔΨΩονϯαʔϏε͕ डΠϕϯτΛফඅ1&/%*/(ঢ়ଶͱ͢Δ
ΦʔέετϨʔγϣϯͷαʔΨΩονϯαʔϏε͕ ༻ҙΠϕϯτΛൃߦ
ΦʔέετϨʔγϣϯͷαʔΨΦʔέετϨλʔͱͯ͠ ༻ҙΠϕϯτΛফඅ
ΦʔέετϨʔγϣϯͷαʔΨձܭαʔϏεʹΫϨδοτܾࡁґཔΠϕϯτΛൃߦ
ΦʔέετϨʔγϣϯͷαʔΨΫϨδοτܾࡁґཔΠϕϯτΛ ফඅ ܾࡁΛߦ͏
ΦʔέετϨʔγϣϯͷαʔΨΫϨδοτܾࡁྃΠϕϯτΛ ൃߦ
ΦʔέετϨʔγϣϯͷαʔΨΫϨδοτܾࡁྃΠϕϯτফඅΩονϯαʔϏεʹܾࡁྃΠϕϯτΛൃߦ
ΦʔέετϨʔγϣϯͷαʔΨ ϝϦοτ• ॥ґଘͳ͠• ؔ͢ΔαʔϏεͷΠϕϯτΛαϒεΫϥΠϒ͢Δඞཁ͕ͳ͍• ίϨΦάϥϑΟΑΓεςʔλεΛ࣋ͨͳ͍ͨΊɺϩδοΫ͕୯७ʹ
ΦʔέετϨʔγϣϯͷαʔΨ ϝϦοτ• ΦʔέετϨʔλʹϏδωεϩδοΫ͕ ूத͘͢͠ͳΔ ίʔσΟωʔτ͚ͩΛߦ͏Α͏ʹ ϏδωεϩδοΫΛഉআ͢Δඞཁ͋Γ• ϫʔΫϑϩʔܗʹͳΔͨΊɺ োʹͳΔՄೳੑ͋Γ
αʔΨͷҙ• ߋ৽σʔλͷࣦ• μʔςΟϦʔυ• ෮ෆೳಡΈऔΓ
αʔΨͷҙ• ࢄॲཧԞ͕ਂ͘қ͕ߴ͍• PHPͰ࣮ݱͤ͞Δͷ͓͢͢Ί͠·ͤΜ• ಘҙͳݴޠɺΈʹͤΑ͏
ES+CQRSͷ ΤοηϯεΛऔΓೖΕΔ
ES+CQRSͷൃల• DDD͚ͷղܾύλʔϯͰ͋Δ͕ɺ ۙͰΤοηϯεΛऔΓೖΕͨ LambdaɺKappaΞʔΩςΫνϟ͕͋Δ (େنσʔλॲཧ͚ not Web App)
KappaΞʔΩςΫνϟ
·ͱΊ
·ͱΊ• Ϗδωεʹؔ৺Λ࣋ͭ͜ͱ͕ୈҰ• نʹ߹Θͤͨσʔλઃܭ ఆظతͳϦϑΝΫλϦϯά ཁ݅ͷੳͰϏδωεΛࢧ͑Δ• దࡐదॴΛݟۃΊΔٕज़
ࣄۀΛࢧ͍͑ͯ͜͏