Upgrade to Pro — share decks privately, control downloads, hide ads and more …

DynamoDB RCU Tunning

Avatar for Quang Hoàng Quang Hoàng
July 18, 2024
40

DynamoDB RCU Tunning

Avatar for Quang Hoàng

Quang Hoàng

July 18, 2024
Tweet

Transcript

  1. HOANG MINH QUANG (クアン) •Joined CyberAgent / Hanoi DevCenter in

    2023/08 •アプ運用カンパニー / 大福山チーム Backend Engineer •Ramen / RDBMS / Go / Design •パフォーマンスチューニング About me @minhquang4334 @Quang4334 #times-hanoi-devcenter ref ref
  2. DynamoDBのRCUとは • 「1RCUで4KBの項目を1秒当たり結果整合性なら 2個を読み込める」 一個は1 Item(レコード)である → 1RCUはMAX 2 Items

    読み込める 読み込めるデータはQueryのレスポンスのデータじゃなくて、スキャンされたデータになる もしfull スキャンになってしまうと、全量データのサイズ・数で計算されてしまう
  3. RCUを減らす、基本的な考え方 1RCUで4KBの項目を1秒当たり結果整合性なら 2個のアイテムを読み込める RCU = f(num_read_requests, total_scan_item_size_per_request) Minimize num_read_requests Minimize

    total_scan_item_size_per_request num_read_requests: DynamoDBのテーブルに読み取りリクエストの数 total_scan_item_size_per_request: 一回の読み取りリクエストでスキャンされるデータ容量
  4. 今の設計の構成 Aurora MySQL DynamoDB Primary Key id is_public is_targeting begin_at

    end_at CampaignMasterTable Partition Key user_id Sort Key campaign_id created_at updated_at TargetingUserCampaignTable データは異なるデータストアに保 存されている
  5. 現状の実装 公開中のキャンペーン一 覧を取得する Aurora MySQL DynamoDB ユーザーにターゲティン グされているユーザーを 絞る ※

    公開中かどうかの情報はAuroraにあり どのユーザーにターゲティングされているか DynamoDBにあるので両方見る必要 課題:あるユーザーに公開中ターゲッティングされているキャンペーン一 (aka Campaign) 覧を取得したい
  6. 現状の実装 公開中のキャンペーン一 覧を取得する SELECT id as public_campaign_ids FROM CampaignMasterTable WHERE

    …… Aurora MySQL DynamoDB ユーザーにターゲティン グされているユーザーを 絞る
  7. 現状の実装 DynamoDBで絞って、 結果返す SELECT campaign_id FROM TargetingUserCampaignTable WHERE CampaignID IN

    (${public_campaign_ids}) AND userId = ? 公開中のキャンペーン一 覧を取得する SELECT id as public_campaign_ids FROM CampaignMasterTable WHERE …… Aurora MySQL DynamoDB ユーザーにターゲティン グされているユーザーを 絞る
  8. 現状の実装 どうやってこのクエリをDynamoDBに叩けるか SELECT campaign_id FROM TargetingUserCampaignTable WHERE CampaignID IN (${public_campaign_ids})

    AND userId = ? 公開中のキャンペーン一 覧を取得する SELECT id as public_campaign_ids FROM CampaignMasterTable WHERE …… Aurora MySQL DynamoDB ユーザーにターゲティン グされているユーザーを 絞る
  9. PartiQLを使用している • a SQL-compatible query language for Amazon DynamoDB なので、複雑なクエリでもDynamoDBでいい感じに叩ける

    WHERE … IN, OR, BETWEEN, ><=><= などで • DB上でページネーション可能 https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html
  10. PartiQLを並列化する PartiQLはWHERE INにあるplaceholdersの数の上限は 100であり、場合によっては50個で、 同時に公開中のキャンペーンが非常に多いため、分割して並列した。 SELECT campaign_id FROM TargetingUserCampaignTable WHERE

    CampaignID IN (${public_campaign_ids_1}) AND userId = ? DynamoDB ユーザーにターゲティン グされているユーザーを 絞る SELECT campaign_id FROM TargetingUserCampaignTable WHERE CampaignID IN (${public_campaign_ids_2}) AND userId = ? SELECT campaign_id FROM TargetingUserCampaignTable WHERE CampaignID IN (${public_campaign_ids_n}) AND userId = ? …… public_campaign_ids = (public_campaign_ids_1, public_campaign_ids_2, .. ,public_campaign_ids_n)
  11. どんどんシステム品質が悪化された • 対象のテーブルの RCU = 5000/s 以上で高い • たまに throttling

    error 発生、サービス不安定 • DynamoDBのコストが高い • APIやシステム全体に P90 Latency が遅い (〜150ms)
  12. 改善策 DynamoDBで結果絞るのではなく、 OnMemoryやる方針にしました DynamoDBで結果絞る SELECT campaign_id FROM TargetingUserCampaignTable WHERE CampaignID

    IN (${public_campaign_ids}) AND userId = ? 公開中のキャンペーン一 覧を取得する SELECT id as public_campaign_ids FROM CampaignMasterTable WHERE …… Aurora MySQL DynamoDB ユーザーにターゲティン グされているユーザーを 絞る 改善前
  13. 改善策 DynamoDBで結果絞るのではなく、 OnMemoryやる方針にしました 公開中のキャンペーン一 覧を取得する Aurora MySQL DynamoDB ユーザーの全ターゲティ ングキャンペーン取得す

    る 公開中かどうか関わらず それぞれ実行して、On MemoryでOverlap された データ(共通部分)を結果 にする 改善策 SELECT id as public_campaign_ids FROM CampaignMasterTable WHERE …… DynamoDB.GetItem by userID partition key つまり userIDのpartitionの全データをとる
  14. RCU最適 1RCUで4KBの項目を1秒当たり結果整合性なら 2個を読み込める RCU = f(num_read_requests, total_scan_item_size_per_request) Minimize num_read_requests Minimize

    total_scan_item_size_per_request 並列化をやめて、一回の Queryだけで行う Queryで必要なデータだけ読 み込める
  15. EOF