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
ZOZOTOWNの検索APIにキャッシュを導入、実装時の工夫や効果について
Search
Satto
March 22, 2023
Technology
2.2k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ZOZOTOWNの検索APIにキャッシュを導入、実装時の工夫や効果について
Satto
March 22, 2023
Other Decks in Technology
See All in Technology
私がブラウザを自作したくなった理由
supurazako
1
250
Agent 時代の Kaggle 展望 / kaggle-in-the-agentic-era
upura
1
800
今こそ聞きたいソフトウェア設計 ドメイン駆動設計再入門
masuda220
PRO
17
7.5k
エンドユーザー視点で見る SansanのMeraki活用と内製自動化
sansantech
PRO
0
100
システム思考で問題に対処する
yussak
0
330
Bill One 開発エンジニア 紹介資料
sansan33
PRO
7
20k
TypeScript入門 2026
recruitengineers
PRO
3
670
SmartHR Engineering Team Deck
smarthr
1
2.3k
Kiro Crew入門 - 常駐エージェントの仕組みと使いどころ / Intro to Kiro Crew
k_adachi_01
1
350
修正PRを食べてレビュースキルが賢くなる:Claude Codeによる自己改善サイクル
yuyaumetsu
6
1.6k
まちスペース®とデジタルツインと「まちづくり」
hiro_ogi
0
130
LanceDB入門
mocobeta
8
580
Featured
See All Featured
WCS-LA-2024
lcolladotor
0
800
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
340
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
460
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
650
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
420
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
201
75k
How to Ace a Technical Interview
jacobian
281
24k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.5k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
53k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
67k
The Curse of the Amulet
leimatthew05
2
14k
Transcript
Spring Boot+Redis Cache 検索APIにキャッシュを導入、実装時の工夫や効果 2022年3月23日 ZOZO Tech Meetup 株式会社ZOZO 技術本部
検索基盤部 検索基盤ブロック 佐藤 由弥 Copyright © ZOZO, Inc. 1
© ZOZO, Inc. 株式会社ZOZO 技術本部 検索基盤部 検索基盤ブロック 佐藤 由弥 •
2020年4月新卒として入社(今年4月で4年目) • 入社当時はJava未経験 ◦ 検索マイクロサービスの開発や運用業務を通じて習得 • 最近の主な業務は検索ページのフロントエンドリプレイス ◦ レガシーコードをJavaに置き換え • 扱う言語やサービス:Java・Python・VBS・Elasticsearch・BigQuery • 趣味:ゲーム、最近はホグワーツに入学 2
© ZOZO, Inc. Agenda 1. ZOZOTOWNの検索について 2. キャッシュの導入 3. 実装時の工夫
4. まとめ 5. おまけ(フロントエンドリプレイスの話) 3
© ZOZO, Inc. Agenda 1. ZOZOTOWNの検索について 2. キャッシュの導入 3. 実装時の工夫
4. まとめ 5. おまけ(フロントエンドリプレイスの話) 4
© ZOZO, Inc. 5 突然ですが!
© ZOZO, Inc. 6 ZOZOTOWNの検索と聞いて何を思い浮かべますか?
© ZOZO, Inc. 以下を思い浮かべた方、正解です! 7 ZOZOTOWNの検索について 世代別ランキング 類似画像検索 サジェスト パーソナライズ化された商品の並び順
これ以外にも沢山あるよ 検索フォーム
© ZOZO, Inc. 8 ZOZOTOWNの検索を支えるシステム構成 • 検索API:Elasticsearchから商品情報を受け取り、ZOZOTOWNへ検索機能を提供 • インデクシングバッチ:DBからElasticsearchへ商品情報を定期的に同期するバッチ
© ZOZO, Inc. 検索システムとして大切な要素 9 今日話すこと • 速度 • 精度
• 可用性 • 再現性などなど
© ZOZO, Inc. 検索システムとして大切な要素 10 今日話すこと • 速度 ◦ 検索APIにキャッシュ導入
• 精度 • 可用性 • 再現性などなど 本資料ではここを深掘る
© ZOZO, Inc. Agenda 1. ZOZOTOWNの検索について 2. キャッシュの導入 3. 実装時の工夫
4. まとめ 5. おまけ(フロントエンドリプレイスの話) 11
© ZOZO, Inc. 12 キャッシュ導入に至った背景
© ZOZO, Inc. 13 検索APIにキャッシュを導入した背景、その1 マイクロサービス化に伴い検索APIの直接参照の機会が増加、負荷面に懸念が出てきた
© ZOZO, Inc. 14 検索APIにキャッシュを導入した背景、その2 検索APIのABテスト実施にあたりWebサイト側の修正も必要、改善サイクルが回りづらい
© ZOZO, Inc. 15 キャッシュ導入のシステム全体像
© ZOZO, Inc. 16 ZOZOTOWNの検索を支えるシステム構成(キャッシュ導入後) Amazon ElastiCache for Redisを追加 キャッシュのやり取りはJavaで実装
© ZOZO, Inc. 17 キャッシュ導入による効果
© ZOZO, Inc. 18 ZOZOTOWNの検索を支えるシステム構成(キャッシュ導入後) Elasticsearchを経由せず、高速に検索結果を返却可能
© ZOZO, Inc. 19 キャッシュ導入による効果(工夫を含めた最終的な効果) • 速度改善に効果あり ◦ 最終的に殆どのエンドポイントで 50ms~100msほどレイテンシが低下
◦ 特に効果があったエンドポイントはp99で94%改善 • 安定した速度で検索結果の提供が可能に ◦ レイテンシの振れ幅が少なくなり安定した 例)世代別ランキングAPIのレイテンシの様子 ※ この後紹介する様々な工夫を取り入れた後の 最終的なレイテンシの低下を表しています 90%以上改善
© ZOZO, Inc. Agenda 1. ZOZOTOWNの検索について 2. キャッシュの導入 3. 実装時の工夫
4. まとめ 5. おまけ(フロントエンドリプレイスの話) 20
© ZOZO, Inc. 21 実装時の工夫 • エンドポイントごとにTTLを最適化 ◦ エンドポイントごとにTTLを延長してレイテンシを計測 ◦
最適な値になるまで上記を繰り返す • キャッシュキーの最適化 ◦ セールの開始時にキャッシュが切り替わるように キャッシュキーにタイムセクションを追加 ◦ Cache Stampedeの対策 • キャッシュのGZIP圧縮 ◦ 検索結果をそのままキャッシュすると ネットワークI/Oやストレージが逼迫 ここを深掘る リンク:https://techblog.zozo.com/entry/implement-cache-in-search-microservice 割愛:詳細はテックブログ参照ください
© ZOZO, Inc. 22 キャッシュのGZIP圧縮の概要 • どんな課題があった? ◦ 登録するキャッシュは、商品の様々な情報を含むためデータサイズが大きい ◦
RedisのネットワークI/Oやストレージの使用量が増加 • なにが嬉しい? ◦ Redisに保存するデータを圧縮することで、 ネットワークI/Oやストレージの使用量を減らし、検索APIの高速化を図る • この後の話 ◦ 実際のJavaのコードを交えて、どのようにGZIP圧縮したか詳細を説明
© ZOZO, Inc. 23 Spring bootからRedisにキャッシュを保存するまでの流れ Redisはインメモリデータストアのため、オブジェクトをデータ形式に変換して保存が必要 扱うRedisクライアント:spring-boot-starter-data-redis https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data- redis
• シリアライズ/デシアライズは JdkSerializationRedisSerializerクラスで行われる • オブジェクトのシリアライズを可能にするには 追加する Redisクライアント Redis シリアライズ 検索結果オブジェクト バイト配列 キャッシュ保存 デシリアライズ キャッシュ読み取り バイト配列 検索結果オブジェクト 同 じ 検索API Icon made by flaticon from https://www.flaticon.com/
© ZOZO, Inc. 24 キャッシュのGZIP圧縮 シリアライズ gzip 圧縮 約60%~80%圧縮 GZIP圧縮の流れ
• serialize() ◦ オブジェクトをシリアライズするメソッド ◦ isGzipEnabledでGZIP実行有無を制御 • compress() ◦ バイト配列をGZIP圧縮するメソッド ◦ GZIPOutputStreamにByteArrayOutputStreamを 渡すことで出力先はバイト配列になる 検索結果オブジェクト バイト配列 圧縮されたバイト配列 Icon made by flaticon from https://www.flaticon.com/
© ZOZO, Inc. 25 キャッシュのGZIP圧縮 シリアライズ gzip 圧縮 約60%~80%圧縮 GZIP圧縮の流れ
• serialize() ◦ オブジェクトをシリアライズするメソッド ◦ isGzipEnabledでGZIP実行有無を制御 • compress() ◦ バイト配列をGZIP圧縮するメソッド ◦ GZIPOutputStreamにByteArrayOutputStreamを 渡すことで出力先はバイト配列になる 検索結果オブジェクト バイト配列 圧縮されたバイト配列 Icon made by flaticon from https://www.flaticon.com/
© ZOZO, Inc. 26 キャッシュのGZIP圧縮 シリアライズ gzip 圧縮 約60%~80%圧縮 GZIP圧縮の流れ
• serialize() ◦ オブジェクトをシリアライズするメソッド ◦ isGzipEnabledでGZIP実行有無を制御 • compress() ◦ バイト配列をGZIP圧縮するメソッド ◦ GZIPOutputStreamにByteArrayOutputStreamを 渡すことで出力先はバイト配列になる 検索結果オブジェクト バイト配列 圧縮されたバイト配列 Icon made by flaticon from https://www.flaticon.com/
© ZOZO, Inc. 27 キャッシュのGZIP圧縮 GZIP解凍の流れ gzip 解凍 デシリアライズ •
deserialize() ◦ Redisから取得した圧縮データを復元するためのメソッド ◦ バイト配列からオブジェクトに変換 • decompress() ◦ 圧縮されたバイト配列を解凍するメソッド ◦ データの解凍と解凍されたデータをバイト配列に書き込む ◦ 一連の流れは煩雑化しやすいので IOUtilsクラスのcopyメソッドを使い簡略化 検索結果オブジェクト バイト配列 圧縮されたバイト配列 Icon made by flaticon from https://www.flaticon.com/
© ZOZO, Inc. 28 キャッシュのGZIP圧縮 GZIP解凍の流れ gzip 解凍 デシリアライズ •
deserialize() ◦ Redisから取得した圧縮データを復元するためのメソッド ◦ バイト配列からオブジェクトに変換 • decompress() ◦ 圧縮されたバイト配列を解凍するメソッド ◦ データの解凍と解凍されたデータをバイト配列に書き込む ◦ 一連の流れは煩雑化しやすいので IOUtilsクラスのcopyメソッドを使い簡略化 検索結果オブジェクト バイト配列 圧縮されたバイト配列 Icon made by flaticon from https://www.flaticon.com/
© ZOZO, Inc. 29 キャッシュのGZIP圧縮 GZIP解凍の流れ gzip 解凍 デシリアライズ •
deserialize() ◦ Redisから取得した圧縮データを復元するためのメソッド ◦ バイト配列からオブジェクトに変換 • decompress() ◦ 圧縮されたバイト配列を解凍するメソッド ◦ データの解凍と解凍されたデータをバイト配列に書き込む ◦ 一連の流れは煩雑化しやすいので IOUtilsクラスのcopyメソッドを使い簡略化 検索結果オブジェクト バイト配列 圧縮されたバイト配列 Icon made by flaticon from https://www.flaticon.com/
© ZOZO, Inc. 30 キャッシュのGZIP圧縮 • spring-boot-starter-data-redis ◦ RedisTemplateが用意されている ◦
Redisとのデータ操作が簡略化 • RedisTemplate ◦ デフォルトシリアライザーの JdkSerializationRedisSerializerをラップ したクラスに差し替える Redisを扱うための依存関係 RedisTemplateにてラップしたクラスに差し替える 元のRedisTemplate ※ テンプレートが異なる場合、適宜差し替え場所を変える
© ZOZO, Inc. 31 キャッシュ圧縮による効果 • ElastiCacheメモリ使用率が約1/3に減少 • ネットワーク通信量が約1/7に減少 懸念していたCPU使用率は変化なし
◦ 約200KBの文字列で構成されたレスポンス情報の圧縮なので サイズが小さく負荷がかからなかった ◦ リソースが十分に与えられたPod上で実行されているため 影響が少なかった キャッシュ圧縮によって、以下の効果が得られた ElastiCacheメモリ使用率 ネットワーク通信量 CPU使用率 約1/3減少 約1/7減少
© ZOZO, Inc. Agenda 1. ZOZOTOWNの検索について 2. キャッシュの導入 3. 実装時の工夫
4. まとめ 5. おまけ(フロントエンドリプレイスの話) 32
© ZOZO, Inc. 33 まとめ/学んだこと まとめ • 速度改善の一環で検索APIにキャッシュを導入 • 殆どのエンドポイントで50~100msほどレイテンシが低下
• GZIPによるキャッシュ圧縮/解凍の実装方法を紹介 • ストレージやネットワーク使用量が低下 学んだこと • Java完全理解 ◦ ほぼ未経験でしたが、実装をある程度任せてもらえたので理解が深まった • レイテンシをより意識するように • 闇雲な改善は良くない ◦ 計測→仮説→実装の流れが大切
© ZOZO, Inc. Agenda 1. ZOZOTOWNの検索について 2. キャッシュの導入 3. 実装時の工夫
4. まとめ 5. おまけ(フロントエンドリプレイスの話) 34
© ZOZO, Inc. 35 おまけ(フロントエンドリプレイスの話) これまでのZOZOTOWNの課題 • Webサーバの技術スタックがレガシー ◦ Classic
ASP・jQuery・ES5 ◦ 他言語でよくある便利機能は自作が必要で開発速度が鈍化 • ビューロジックが独自テンプレートエンジンで実現 ◦ コードが独特で癖があり実装コストが高い ◦ ビューとAPI側にビジネスロジックが分散 リプレイス後のZOZOTOWN ※ 説明のため簡略化しています
© ZOZO, Inc. 36 最後に 「検索のバックエンドに興味ある方」や「リプレイスに興味ある方」を募集しています カジュアル面談もあるので気軽にどうぞ! 求人ページ:https://hrmos.co/pages/zozo/jobs/0000034