Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
事業のスケールアウトを支える PHPで作る分散アーキテクチャ
Search
yuuki takezawa
December 11, 2020
Technology
4
4.9k
事業のスケールアウトを支える PHPで作る分散アーキテクチャ
事業の成長と、それにともなうアプリケーションの課題、
発生しがちな問題を追いながら、
解決策の一つであるCQRS導入について解説します。
分散システムで発生する問題についても軽く触れていきます。
yuuki takezawa
December 11, 2020
Tweet
Share
More Decks by yuuki takezawa
See All by yuuki takezawa
なぜAI時代に 「イベント」を中心に考えるのか? / Why focus on "events" in the age of AI?
ytake
3
1.2k
PHPでアクターモデルを活用したSagaパターンの実践法 / php-saga-pattern-with-actor-model
ytake
0
1.8k
PHP ステートレス VS ステートフル 状態管理と並行性 / php-stateless-stateful
ytake
0
180
PHPでアクターモデルを理解・体験しよう / Understand and experience the actor model in PHP
ytake
2
640
再考 アクターモデル/ reconsider actor model
ytake
0
1.3k
GoとアクターモデルでES+CQRSを実践! / proto_actor_es_cqrs
ytake
1
530
Phluxorでアクターモデルを 理解・体験しよう / toolkit-for-flexible-actor-models-in-php-phluxor
ytake
1
310
オブジェクトのおしゃべり大失敗 メッセージングアンチパターン集 / messaging anti-pattern collection
ytake
2
1.2k
DRE/SREのプラクティス融合によるクラウドネイティブなデータ基盤作り / dre_sre
ytake
0
880
Other Decks in Technology
See All in Technology
UDDのススメ - 拡張版 -
maguroalternative
1
550
[OCI Technical Deep Dive] OracleのAI戦略(2025年8月5日開催)
oracle4engineer
PRO
1
170
LTに影響を受けてテンプレリポジトリを作った話
hol1kgmg
0
370
LLM 機能を支える Langfuse / ClickHouse のサーバレス化
yuu26
9
2.2k
猫でもわかるQ_CLI(CDK開発編)+ちょっとだけKiro
kentapapa
0
3.5k
アカデミーキャンプ 2025 SuuuuuuMMeR「燃えろ!!ロボコン」 / Academy Camp 2025 SuuuuuuMMeR "Burn the Spirit, Robocon!!" DAY 1
ks91
PRO
0
150
20250807 Applied Engineer Open House
sakana_ai
PRO
2
390
大規模イベントに向けた ABEMA アーキテクチャの遍歴 ~ Platform Strategy 詳細解説 ~
nagapad
0
230
Intro to Software Startups: Spring 2025
arnabdotorg
0
260
Kiroでインフラ要件定義~テスト を実施してみた
nagisa53
3
360
生成AIによるソフトウェア開発の収束地点 - Hack Fes 2025
vaaaaanquish
29
13k
Oracle Exadata Database Service on Cloud@Customer X11M (ExaDB-C@C) サービス概要
oracle4engineer
PRO
2
6.3k
Featured
See All Featured
Designing Experiences People Love
moore
142
24k
GitHub's CSS Performance
jonrohan
1031
460k
Building an army of robots
kneath
306
45k
RailsConf 2023
tenderlove
30
1.2k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4k
Build your cross-platform service in a week with App Engine
jlugia
231
18k
Java REST API Framework Comparison - PWX 2021
mraible
33
8.8k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Gamification - CAS2011
davidbonilla
81
5.4k
Making Projects Easy
brettharned
117
6.3k
Thoughts on Productivity
jonyablonski
69
4.8k
Music & Morning Musume
bryan
46
6.7k
Transcript
ࣄۀͷεέʔϧΞτΛࢧ͑Δ PHPͰ࡞ΔࢄΞʔΩςΫνϟ Yuuki Takezawa / ytake
Pro f i le • ᖒ ༗و / 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(): \Generato r { 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/BNF QSJDF TBMFT1FSJPE
ڥք͚ΒΕͨίϯςΩετ ໊ ݸ ૹઌͰ͢
ڥք͚ΒΕͨίϯςΩετ QSPEVDU/BNF LJUDIFO/BNF QSJDF TBMFT1FSJPE RVBOUJUZ TJQQJOH"EESFTT
ڥք͚ΒΕͨίϯςΩετ ໊ ஈͰ͢
ڥք͚ΒΕͨίϯςΩετ QSPEVDU/BNF LJUDIFO/BNF QSJDF TBMFT1FSJPE RVBOUJUZ TJQQJOH"EESFTT
ڥք͚ΒΕͨίϯςΩετ • ͱ͍͏ݴ༿Ͱ༰͕ҟͳΔ • ΞϓϦέʔγϣϯͰଟʑ • ڞ௨ԽͰ͖ΔͷͰͳ͍
ڥք͚ΒΕͨίϯςΩετ • ྫ͑ɺΛࢦ͢ݴ༿ͱ DB্ͷproductsςʔϒϧҰக͠ͳ͍ έʔε͕ଟ͍ • ͲͪΒ͔ʹ߹ΘͤΒΕΔͷͰͳ͍ͱ
ೝࣝ͢Δ͜ͱ
ॻ͖ࠐΈͱಡΈࠐΈΛ ͯ͠ΈͯͲ͏͔
CQRS
CQRS • ॻ͖ࠐΈϞσϧͱಡΈࠐΈϞσϧΛִ • υϝΠϯϞσϧͷ͚ͩͰͳ͘ σʔλετΞ͢ΒཧతʹผʹՄೳ ؔ৺ࣄͷΛపఈ
• DDDʹ͓͚ΔಡΈࠐΈͱॻ͖ࠐΈͷࠩΛղܾ͢Δ ύλʔϯ
CQRS
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 / Con f l uent ͳͲ)
Event Sourcing CQRS
CQRS
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ΞʔΩςΫνϟ
KappaΞʔΩςΫνϟ
·ͱΊ
·ͱΊ • Ϗδωεʹؔ৺Λ࣋ͭ͜ͱ͕ୈҰ • نʹ߹Θͤͨσʔλઃܭ ఆظతͳϦϑΝΫλϦϯά ཁ݅ͷੳͰϏδωεΛࢧ͑Δ •
దࡐదॴΛݟۃΊΔٕज़
ࣄۀΛࢧ͍͑ͯ͜͏