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
replace of cart system on ZOZOTOWN
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
TakahashiKazutaro
March 24, 2023
Technology
2.3k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
replace of cart system on ZOZOTOWN
TakahashiKazutaro
March 24, 2023
More Decks by TakahashiKazutaro
See All by TakahashiKazutaro
ZOZOTOWNトップページの裏側 / Back side of the ZOZOTOWN top page
takahashikazutaro
2
5.9k
Other Decks in Technology
See All in Technology
データエンジニアの困りごとをDevinと一緒に解消する
10xinc
2
790
推論の観測、できていますか? 〜 Google Cloud Gemini Enterprise Agent Platformで 3つの Gemini モデルを実測して踏んだ、評価の罠 〜
shukob
PRO
0
140
Guerilla InnerSource in enterprises, during the AI hype
onenashev
PRO
0
140
【視聴者参加型!】AWSセキュリティアンチパターンクイズ
syoshie
0
250
『止めない』を設計する — 制約の中で、事業の根幹を支える判断
hiroyaterui
0
160
Genie Code ワークショップ 応用編 / Genie-Code-Workshop-advanced
databricksjapan
PRO
0
310
Bet AI Day 2026丨AIを「使う」から、AIが「働く」へ ― LayerXが進める「組織AI」の社会実装
layerx
PRO
2
2.1k
AIとペアプロを始める。人とのペアプロをやめる。ペアプロの良さを改めて知る。もっと好きになった。 / Rediscovering Pair Programming
honyanya
1
190
いかに伝えるか 〜新卒エンジニアの教育のための、ライトノベル活用の一例
ikedon
1
190
Level Up Your CDK DX: 5 Tools I’ve Been Building
gotok365
2
190
DINO-EdgeQuery:Edge-First Polygon Decoding for Building Footprint Extraction from Satellite Imagery
lehupa
0
140
DGX Sparkを2台使って いろいろ動かす話
sonoda_mj
1
120
Featured
See All Featured
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
400
Building Flexible Design Systems
yeseniaperezcruz
330
41k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
6.1k
How to build a perfect <img>
jonoalderson
1
5.9k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
6
1.2k
Become a Pro
speakerdeck
PRO
31
6.2k
Thoughts on Productivity
jonyablonski
76
5.4k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.3k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
570
Test your architecture with Archunit
thirion
2
2.4k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.1k
The Cost Of JavaScript in 2023
addyosmani
55
10k
Transcript
ZOZOTOWNカート決済システムのリ プレイス〜歩みとこれから〜 2023-03-23 ZOZO Tech Meetup〜Java活用事例紹介〜 株式会社ZOZO 技術本部 カート決済部 カート決済基盤ブロック
高橋 和太郎 Copyright © ZOZO, Inc. 1
© ZOZO, Inc. 株式会社ZOZO 技術本部 カート決済部 カート決済基盤ブロック 高橋 和太郎 2019年よりZOZOTOWNリプレイスプロジェクトに参画し、
2021年よりカート決済システムリプレイスに従事。趣味は猫 と遊ぶこと。 2
© ZOZO, Inc. https://zozo.jp/ • ファッションEC • 1,500以上のショップ、8,500以上のブランドの取り扱い • 常時90万点以上の商品アイテム数と毎日平均2,600点以上の新着
商品 を掲載(2022年12月末時点) • ブランド古着のファッションゾーン「ZOZOUSED」や コスメ専門モール「ZOZOCOSME」、靴の専門モール 「ZOZOSHOES」、ラグジュアリー&デザイナーズゾーン 「ZOZOVILLA」を展開 • 即日配送サービス • ギフトラッピングサービス • ツケ払い など 3
© ZOZO, Inc. 4 Agenda • カートリプレイスについて • カートリプレイスPhase1 •
カートリプレイスPhase2 • 技術選定・ツール • 部内の取り組み • リプレイスの今後
© ZOZO, Inc. 5 カートリプレイスについて
© ZOZO, Inc. カートリプレイスのこれまで Qiita: ZOZO開発組織の2022年の振り返りと現状 6 ※ 2022年12月公開時点
© ZOZO, Inc. カートリプレイスの目的 成長し続けるZOZOTOWNを支え、お客様にいつでも快適に買い物をしていただけるサービスを提供 するため • セールなどの高負荷イベントに対応できること ◦ スケール可能であること
◦ キャパシティコントロールが可能であること • Datadog、SentryなどのSaaSを利用した運用監視の効率化ができること • CI/CDなどを取り入れ、開発生産性を向上できること • レガシー技術をモダン化できること 7
© ZOZO, Inc. 8 カートリプレイスPhase1
© ZOZO, Inc. カートリプレイス前の構成概要 • リクエストをIISで受け、VBScriptからSQL Serverのストアドプロシージャを呼び出し、処理を実行 • ストアドプロシージャでは、在庫の引き当てとカート投入処理を実施 9
© ZOZO, Inc. 構成概要 TECH BLOG:ZOZOTOWN カート決済機能リプレイス Phase1 〜 キャパシティコントロールの実現
10
© ZOZO, Inc. Cart Queuing Systemの概要 11
© ZOZO, Inc. 12 カートリプレイスPhase2
© ZOZO, Inc. 構成概要(Before) 13
© ZOZO, Inc. 構成概要(After) 14
© ZOZO, Inc. Cart Stock Systemの概要 • 在庫情報テーブルで在庫を管理 • オンプレの在庫情報との整合性を担保するために在庫変更ログテーブルを使用
15
© ZOZO, Inc. 16 技術選定・ツール
© ZOZO, Inc. 技術選定・開発ツールについて 社内のOSS利用ガイドラインに基づいて実施 • Javaのバージョン • Spring Bootのバージョン
• ソフトウェアアーキテクチャ • ビルドツール • テストフレームワーク • AWSの使用サービス • ライブラリ ◦ O/R Mapper ◦ コードフォーマッター ◦ DBマイグレーションツール ◦ OpenAPI 17 開発に使用しているツール • IntelliJ IDEA • GitHub ◦ GitHub Actions ▪ 単体テスト ▪ コードの自動フォーマット ▪ 必要に応じてDocker Imageの作成 • Sentry • Datadog ◦ 監視 ◦ 分析 • SonarCloud ◦ 静的コード解析 カート決済専任のSREがいるため、インフラ面で気軽に相談ができる
© ZOZO, Inc. 検討中概要 • APIからSQL Serverのストアドプロシージャの呼び出しを想定 • Java +
Spring Bootを使用して実現するためのライブラリの選定などを実施中 18
© ZOZO, Inc. 技術選定 要件 • APIからSQL Serverのストアドプロシージャを呼び出す • ストアドプロシージャは複数のResultSetを返
す 検証対象ライブラリ(O/R Mapper) • JPA • Spring Data JDBC • MyBatis • Doma 2 比較内容 • レイテンシ • コード量 19
© ZOZO, Inc. 技術選定(JPA) 20 • 平均レイテンシ:45ms • コード量: •
問題点:2つ目のResultSetを取得する ために2回目のDB接続が必要 StoredProcedureQuery procedureQuery = createStoredProcedure( entityManager.createStoredProcedureQuery( "SampleProcedure", SampleProcedure.class)); setParameterForProcedure(procedureQuery, id); // 1回目の実行 if(procedureQuery.execute()) { // Outputパラメータ取得 Integer outputId = (Integer) procedureQuery.getOutputParameterValue("OutputId"); // 1つ目のResultSetの取得 List<FirstResult> firstResults = procedureQuery.getResultList(); // 2回目の実行準備 procedureQuery = createStoredProcedure( entityManager.createStoredProcedureQuery( "SampleProcedure", SampleProcedure.class)); setParameterForProcedure(procedureQuery, id); List<SecondResult> secondResults = new ArrayList<>(); if(procedureQuery.hasMoreResults()) { // 2つ目のResultSetの取得 secondResults = procedureQuery.getResultList(); }
© ZOZO, Inc. 技術選定(Spring Data JDBC) 21 • 平均レイテンシ:22ms •
コード量:他のライブラリに比べると多 い CallableStatement callableStatement = connection.prepareCall("{call SampleProcedure(?,?)}"); callableStatement.setLong("id", id.value()); callableStatement.registerOutParameter("OutputId", Types.INTEGER); // 1つ目のResultSetの取得 ResultSet firstResultSet = callableStatement.executeQuery(); List<FirstResult> firstResults = new ArrayList<>(); while(firstResultSet.next()) { firstResults.add(new FirstResult( new Id(firstResultSet.getLong("Id")), new Name(firstResultSet.getString("Name")); } List<SecondResult> secondResults = new ArrayList<>(); if(callableStatement.getMoreResults()) { // 2つ目のResultSetの取得 ResultSet secondResultSet = callableStatement.getResultSet(); while(secondResultSet.next()) { secondResults.add(new SecondResult( new ItemId(secondResultSet.getLong("ItemId")), new ItemName(secondResultSet.getString("ItemName"))); } }
© ZOZO, Inc. 技術選定(MyBatis) 22 • 平均レイテンシ:149ms • コード量:Repository層としての量は少ないが、XMLにストアドプロシージャ呼び出し用の定義を書くため、全体とし てはあまり少なくならない
List<Map<String, Object>> resultSet = procedureMapper.executeSampleProcedure(id.value(),name); // 1つ目のResultSetを取得 List<Object> firstResultObjects = (List<Object>) resultSet.get(0); List<FirstResult> firstResults = new ArrayList<>(); for (Object obj: firstResultObjects) { FirstResult firstResult = (FirstResult) obj; firstResults.add(new FirstResult( new Id(firstResult.getId())), new Name(firstResult.getName()); } // 2つ目のResultSetを取得 List<Object> secondResultObjects = (List<Object>) resultSet.get(1); List<SecondResult> secondResults = new ArrayList<>(); for (Object obj: secondResultObjects) { SecondResult secondResult = (SecondResult) obj; secondResults.add(new SecondResult( new ItemId(secondResult.getItemId())), new ItemName(secondResult.getItemName()); } <mapper namespace="jp.xxx.api.infrastructure.mappers.SampleProcedureMapper"> <resultMap id="FirstResultSet" type="jp.xxx.api.infrastructure.models.FirstResultSet"> <result property="id" column="Id"/> <result property="name" column="Name"/> </resultMap> <resultMap id="SecondResultSet" type="jp.xxx.api.infrastructure.models.SecondResultSet"> <result property="itemId" column="ItemId"/> <result property="itenName" column="ItemName"/> </resultMap> <select id="executeSampleProcedure" resultMap="FirstResultSet,SecondResultSet" statementType="CALLABLE" > {call SampleProcedure(#{id,jdbcType=BIGINT,mode=IN}, #{name,jdbcType=VARCHAR,mode=OUT})} </select> </mapper>
© ZOZO, Inc. 技術選定(Doma 2) 23 • 平均レイテンシ:19ms • コード量:ライブラリ内に必要なアノテーションが用意されており、コード量はかなり少ない
◦ ドメインオブジェクトへの変換もアノテーションにより可能 @Procedure(name = "SampleProcedure") void execute( @ResultSet(ensureResultMapping = true) List<FirstResult> firstResults, @ResultSet(ensureResultMapping = true) List<SecondResult> secondResults, @In Id id, @Out Reference<OutputId> outputId); import org.seasar.doma.Domain; @Domain(valueType = Long.class, accessorMethod = "value") public record Id(Long value) { }
© ZOZO, Inc. 24 技術選定のまとめ 平均レイテンシ コード量 複数ResultSetのDB接続回数 Doma 2
19 ms 少 1回 Spring Data JDBC 22 ms 多 1回 JPA 45 ms 中 n回 MyBatis 149 ms 多 1回
© ZOZO, Inc. 25 部内の取り組み
© ZOZO, Inc. 部内でのJavaへの取り組み カート決済部 • 事業案件を担当するチーム ◦ VBScriptを使用して開発 ◦
今後リプレイスしたコードも管理していく • リプレイスを担当するチーム 事業案件を担当するチームでの取り組み • Java未経験者もいたが、外部講師によるJava講習会を受講して基礎を身につけた • チーム内でJavaを使用した勉強会を週に2回程度実施 26
© ZOZO, Inc. 27 リプレイスの今後
© ZOZO, Inc. リプレイスのこれから Qiita: ZOZO開発組織の2022年の振り返りと現状 28 ※ 2022年12月公開時点
© ZOZO, Inc. 29 一緒にカート決済部で働く仲間を募集しています
None