メモリストア

*このコンテンツは、ベータ版のAI(人工知能)を使用して翻訳されており、エラーが含まれている可能性があります。このページを英語で表示するには、 こちら をクリックしてください。

MemoryStoreService は、ライブセッションのすべてのサーバーからアクセス可能な高速メモリ内データストレージを提供する高速通信量と低遅延データサービスです。 メモリストア は、速く変更し、持続する必要がない頻繁で一時的なデータに適しており、アクセスが迅速で最大寿命に達すると消滅するため、持続性が必要ない。セッション間で持続する必要があるデータには、データストア を使用します。

データ構造

生データに直接アクセスするのではなく、メモリストアは、クイック処理のためにサーバー間で共有される 3つのプリミティブなデータ構造を持っています:ソートされたマップキュー、およびハッシュマップ。各データ構造は、特定のユースケースに最適です:

  • スキルベースのマッチメイキング - スキルレベルなどのユーザー情報を、サーバー間の共有 キュー に保存し、ロビーサーバーを使用して定期的にマッチメイキングを実行します。
  • クロスサーバー取引とオークション - ユーザーがリアルタイムで変更する価格でアイテムを入札できるユニバーサル取引を有効にし、キー-バリューペアの ソートマップ で排列する。
  • グローバルリーダーボード - ソートされたマップ内の共有リーダーボードでユーザーのランキングを保存し、更新する。
  • 共有インベントリ - ユーザーが相互にインベントリアイテムを利用できる共有 ハッシュマップ で、インベントリアイテムと統計を保存する
  • 持続データのキャッシュ - データストアにデータを同期してコピーして、キャッシュとして機履行し、エクスペリエンスのパフォーマンスを向上させるメモリストアの ハッシュマップ に、持続データを保存します。

一全般に、特定のキーに基づいてデータにアクセスする必要がある場合は、ハッシュマップを使用します。そのデータを注文する必要がある場合は、ソートされたマップを使用します。特定の順序でデータを処理する必要がある場合は、キューを使用します。

制限と枠組み

スケーラビリティとシステムパフォーマンスを維持するために、メモリストアにはメモリサイズ、APIリクエスト、およびデータ構造サイズのデータ使用枠があります。

メモリストアには、期限時間に基づく排除ポリシー、通称ライブ時間(TTL)があります。アイテムは期限切れ後に排除され、メモリクオートが新しいエントリのために解放されます。メモリ制限に達すると、アイテムが期限切れになるか、手動で削除するまで、後続のすべての書き込みリクエストが失敗します。

メモリサイズの割り当て

メモリクオートの制限は、エクスペリエンスが消費できるメモリの合計を制限します。固定値ではありません。代わりに、経過時間に応じて、次の式に従ってエクスペリエンスのユーザー数に応じて変更します: 64KB + 1KB * [ユーザー数] 。クオータはサーバーレベルではなく、エクスペリエンスレベルに適用されます。

ユーザーがエクスペリエンスに参加すると、追加のメモリクオートがすぐに利用可能になります。ユーザーがエクスペリエンスを終了すると、クオータはすぐに減少しません。クオータが低い値に再評価される前の 8日間のトレースバック期間があります。

エクスペリエンスがメモリサイズの制限に達した後、メモリサイズを増加させるすべての API リクエストは常に失敗します。メモリサイズを減少させたり変更しないリクエストは、まだ成功します。

観察可能性ダッシュボードで、メモリ使用量チャートを使用して、実時間でエクスペリエンスのメモリサイズ枠を表示できます。

APIリクエスト制限

API リクエスト制限には、すべての API 呼び出し に適用される MemoryStoreService のクォータがあります。クオータは 1000 + 100 * [同時ユーザー数] 分ごとのリクエストユニットです。

ほとんどの API 呼び出しは、いくつかの例外を除き、1つのリクエストユニットのみを消費します:

  • MemoryStoreSortedMap:GetRangeAsync()

    返されたアイテムの数に基づいてユニットを消費します。たとえば、このメソッドが 10 アイテムを返す場合、呼び出しは 10 リクエストユニットとしてカウントされます。空の応答を返す場合、1つのリクエストユニットとしてカウントされます。

  • MemoryStoreQueue:ReadAsync()

    MemoryStoreSortedMap:GetRangeAsync() と同じように、返されたアイテムの数に基づいてユニットを消費しますが、読み込み中に 2 秒ごとに追加のユニットを消費します。最大読み込み時間を waitTimeout パラメータで指定します。

  • MemoryStoreHashMap:UpdateAsync()

    最低 2 ユニットを消費します。

  • MemoryStoreHashMap:ListItemsAsync()

    消費する [スキャンされたパーティションの数] + [返されたアイテム] ユニット。

リクエスト枠は、サーバーレベルではなくエクスペリエンスレベルにも適用されます。これにより、トータルリクエストレートが制限を超えない限り、サーバー間でリクエストを割り当てることができます。クオータを超えると、サービスがリクエストを制限するとエラー応答が返されます。

観察可能性 機能が利用可能であるため、エクスペリエンスのリクエストユニットクオートをリアルタイムで表示できます。

データ構造サイズ制限

単一のソート済みマップまたはキューには、次のサイズとアイテム数制限が適用されます:

  • 最大アイテム数: 1,000,000
  • 最大総サイズ (ソートされたマップのキーを含む): 100MB

パーティションごとの制限

見る パーティションごとの制限 .

最良の実践

メモリ使用パターンを最適に保ち、制限に達するのを避けるには、次のベストプラクティスに従ってください:

  • 処理されたアイテムを削除する。: キューとソートされたマップの読み込みアイテムを メソッドで一貫してクリーンアップすると、メモリを解放し、データ構造を最新の状態に保つことができます。

  • データを追加するときに、期限時間を可能な最小の時間枠に設定します。: デフォルトの有効期限時間は、MemoryStoreQueue:AddAsync()MemoryStoreSortedMap:SetAsync() の両方で 45 日ですが、最短の可能な時間を設定すると、メモリ使用量の割り当てを満たさないように、古いデータを自動的に削除できます。

    • 長期の期限切れで大量のデータを保存しないでください、これはメモリクオートを超える可能性があり、体験全体を壊滅させる可能性のある問題を引き起こす可能性があります。
    • 必要ないアイテムを明示的に削除するか、短いアイテムの期限を設定することを常に行います。
    • 一般的に、メモリとアイテムの期限切れを安全機能としてリリースするために、明示的な削除を使用して、未使用のアイテムが長期間メモリを占有しないようにする必要があります。
  • メモリに必要な値だけを保持する。

    たとえば、オークションハウスのエクスペリエンスの場合、最高入札を維持するだけで十分です。1つのキーで MemoryStoreSortedMap:UpdateAsync() を使用して、データ構造にすべての入札を保持するのではなく、最高入札を維持できます。

  • 経験値バックオフを使用 して、API リクエスト制限を下に保つのを助けます。

    たとえば、DataUpdateConflict を受け取った場合、2秒後、4、8などで再試行するかもしれません。正しい返答を得るために、MemoryStoreService に連続してリクエストを送信するのではなく、

  • 巨大なデータ構造を シャーディング で複数の小さな構造に分割します。

    すべてを 1つの大きなデータ構造に保存するのではなく、より小さな構造でデータを管理する方が簡単な場合が多いこのアプローチは、使用とレート制限を回避するのにも役立ちます。たとえば、キーにプレフィックスを使用するソートされたマップがある場合、それぞれのプレフィックスを独自のソートマップに分離することを検討してください。特に人気のあるエクスペリエンスの場合、ユーザーのユーザーIDの最後の数字に基づいてユーザーを複数のマップに分けることさえあります。

  • 保存された値を圧縮する。

    たとえば、LZW アルゴリズムを使用して、保存された値のサイズを減少させることを考えてみましょう。

観察可能性

観察可能性ダッシュボード は、メモリストアの使用をモニタリングしてトラブルシューティングするための洞察と分析を提供します。メモリ使用量と API リクエストの異なる面でリアルタイム更新チャートを使用すると、エクスペリエンスのメモリ使用パターンを追跡し、現在割り当てられたクォータを表示し、API ステータスをモニタリングし、パフォーマンス最適化のための潜在的な問題を特定できます。

次の表は、オブザーバビリティダッシュボードの ステータスコード別リクエント数API x ステータス チャートで利用可能な API 応答のすべてのステータスコードをリストし、説明します。これらのエラーを解決する方法に関する詳細は、トラブルシューティング を参照してください。エラーに関連する特定のクオータまたは制限については、制限とクオータ を参照してください。

ステータスコード説明
成功成功した。
データ構造メモリオーバー限度データ構造レベルのメモリサイズ制限(100MB)を超えています。
データ更新の競合同時更アップデートによるコンフリクト。
アクセス拒否エクスペリエンスデータにアクセスする権限がありません。このリクエストは、リクエストユニットを消費したり、クオータを使用したりしません。
内部エラー内部エラー。
無効なリクエストリクエストに必要な情報がないか、不正な情報があります。
データ構造アイテムオーバーリミットデータ構造レベルのアイテムカウント制限(1M)を超えています。
NoItem Found なしMemoryStoreQueue:ReadAsync() または MemoryStoreSortedMap:UpdateAsync() にアイテムが見つかりません。ReadAsync() は 2 秒ごとに調査し、キューにアイテムが見つかるまでこのステータスコードを返します。
データ構造リクエストオーバー限度データ構造レベルリクエストユニット制限(分ごとに 100,000 リクエストユニット)を超えています。
パーティションリクエストオーバー限度パーティションリクエストユニット制限を超えています。
トータルリクエストオーバー制限宇宙レベルのリクエストユニット制限を超えています。
トータルメモリオーバー制限ユニバースレベルのメモリクオータを超えています。
アイテムバリューサイズが大きすぎる値サイズが制限(32KB)を超えています。

次の表は、現在オブザーバビリティダッシュボードで利用できないクライアント側の状態コードをリストしています。

ステータスコード説明
内部エラー内部エラー。
公開されていない場所MemoryStoreService を使用するには、この場所を公開する必要があります。
無効なクライアントアクセスMemoryStoreService はサーバーから呼び出されなければなりません。
無効な期限時間期限の経過時間は 0 から 3,888,000 の間でなければなりません。
無効なリクエスト値をJSONに変換できません。
無効なリクエストsortKeyを有効な数字または文字列に変換できません。
TransformCallback失敗した変換コールバック関数を呼び出すことに失敗しました。
リクエストが制限された最近のメモリストアリクエストは、1つまたは複数の制限に達しました。
更新コンフリクト最大リトライ数を超えました。

問題解決

次の表は、各応答ステータスコードに対する推奨解決策をリストアップし、説明します:

エラートラブルシュートオプション
データ構造リクエストオーバーリミット/パーティションリクエストオーバーリミット

  • 別の変数に情報を保存してローカルキャッシュを追加し、30秒などの特定の時間間隔後に再チェックします。:
  • ステータスでの リクエストカウント チャートを使用して、 NoItemFounds より多くの 成功 応答を受け取っていることを確認します。失敗したリクエストで MemoryStoreService をヒットする回数を制限する。:
  • リクエスト間の短い遅延を実装する。:
  • ベストプラクティスをフォローする
  • , 包括:

      データ構造を大量に受け取った場合、データ構造リクエストオーバーリミット/パーティションリクエストオーバーリミットのレスポンスを分割する。:

    • 適切なレートのリクエストを送信するための幾何級のバックオフを実装する。
トータルリクエストオーバー制限
データ構造アイテムオーバーリミット
  • メモリサイズを減少するために最良の実践を適用する
データ構造メモリオーバー限度
トータルメモリオーバー制限
データ更新の競合
  • リクエストの間に短い遅延を実装して、複数のリクエストが同時に同じキーを更新するのを避けます。:
  • ソートされたマップの場合、次のコードサンプルのように MemoryStoreSortedMap:UpdateAsync() メソッドの callback 機能を使用して、特定の回数の試行後にリクエストをキャンセルします:
  • Example of Aborting Request

    local MemoryStoreService = game:GetService("MemoryStoreService")
    local map = MemoryStoreService:GetSortedMap("AuctionItems")
    function placeBid(itemKey, bidAmount)
    map:UpdateAsync(itemKey, function(item)
    item = item or { highestBid = 0 }
    if item.highestBid < bidAmount then
    item.highestBid = bidAmount
    return item
    end
    print("item is "..item.highestBid)
    return nil
    end, 1000)
    end
    placeBid("MyItem", 50)
    placeBid("MyItem", 40)
    print("done")
  • 調査して、コンフリクトを避けるために効率的に呼び出しているかどうかを確認します。MemoryStoreService理想的には、リクエストを過剰に送るべきではありません。:
  • キューとソートされたマップの両方で MemoryStoreQueue:RemoveAsync() メソッドを使用してアイテムを一貫して削除する。
内部エラー
  • Roblox ステータスページ をチェックします。
  • バグレポートをファイルして、エクスペリエンスのユニバースIDで問題を説明します。
無効なリクエスト
  • リクエストに正しく有効なパラメータを含めることを確認してください。無効なパラメータの例は次のとおりです:
    • 空の文字列
    • 長さ制限を超える文字列
    • >

アイテムバリューサイズが大きすぎる
  • アイテムの値を複数のキーに分割または分割する。
    • グループ化されたキーを整理するには、キーに prefix を追加してアルファベット順に並べ替えます。
  • 保存された値をエンコードまたは圧縮する。

スタジオでテストとデバッグ

MemoryStoreService のデータは、Studio と生産の間で孤立しているので、Studio のデータを変更すると、生産の動作には影響しません。これは、Studio からの API 呼び出しが生産データにアクセスしないことを意味し、生産に移行する前に安全にメモリストアと新機能をテストできるようにします。

スタジオテストには、プロダクションと同じ 制限と枠組みがあります。ユーザー数に基づいて計算されたクォータでは、Studio テスト用の唯一のユーザーであるため、結果のクォータは非常に小さくなります。スタジオからテストすると、アクセスと権限を確認するために実行されるいくつかの追加のチェックにより、生産環境での使用と比較して若干遅延が高くなり、エラー率が上昇する可能性もあります。

ライブエクスペリエンスでメモリストアをデバッグする方法や、スタジオでテストするときの情報については、開発者コンソール を使用します。