Rails でのタイムライン クエリを高速化するためのキャッシングの適切な使用方法についてアドバイスを得たいと思っています。背景は次のとおりです。
Rails バックエンドで iPhone アプリを開発しています。これはソーシャル アプリであり、他のソーシャル アプリと同様に、その主なビューはメッセージのタイムライン (ニュースフィード) です。これは、タイムラインがユーザーとそのフォロワーのメッセージで構成される Twitter と非常によく似ています。タイムラインを取得するための API リクエストの主なクエリは次のとおりです。
@messages = Message.where("user_id in (?) OR user_id = ?", current_user.followed_users.map(&:id), current_user)
現在、このクエリは、特に大規模な場合に非常に非効率になるため、キャッシュを検討しています。やろうとしていることは以下の2点です。
1) Redis を使用してタイムラインをメッセージ ID のリストとしてキャッシュする
このクエリのコストが非常に高くなる理由の 1 つは、オンザフライで表示するメッセージを判断することです。ここでの私の計画は、各ユーザーのメッセージ ID の Redis リストを作成し続けることです。Timeline API リクエストが届いたときにこれを正しくビルドすると仮定すると、Redis を呼び出して、表示するメッセージの ID の前処理済みの順序付きリストを取得できます。たとえば、「[21, 18, 15, 14, 8, 5]」のような結果が得られる場合があります。
2) Memcached を使用して個々のメッセージ オブジェクトをキャッシュする
最初のポイントは大いに役立つと思いますが、データベースから個々のメッセージ オブジェクトを取得するという潜在的な問題がまだ残っています。メッセージ オブジェクトは非常に大きくなる可能性があります。それらを使用して、コメント、いいね、ユーザーなどの関連オブジェクトを返します。理想的には、これらの個々のメッセージ オブジェクトもキャッシュします。これは私が混乱しているところです。
キャッシュを使用しない場合は、次のようなクエリ呼び出しを実行してメッセージ オブジェクトを取得します。
@messages = Message.where("id in (?)", ids_from_redis)
次に、タイムラインを返します。
respond_with(:messages => @messages.as_json) # includes related likes, comments, user, etc.
ここで、Memcache を使用して個々のメッセージ オブジェクトを取得したいので、一度に 1 つずつメッセージを取得する必要があるようです。疑似コードを使用して、次のようなことを考えています。
ids_from_redis.each do |m|
message = Rails.cache.fetch("message_#{m}") do
Message.find(m).as_json
end
@messages << message
end
これが私の2つの具体的な質問です(長いビルドで申し訳ありません):
1) このアプローチは一般的に理にかなっていますか (リストの場合は redis、オブジェクトの場合は memcached)?
2)具体的には、以下の疑似コードでは、これがこれを行う唯一の方法ですか? メッセージを 1 つずつ取得するのは効率が悪いように感じますが、オブジェクト レベルのキャッシュを実行するつもりであるため、他にどのように実行すればよいかわかりません。
このようなことを試みるのはこれが初めてなので、フィードバックに感謝します。