2012-04-04 3 views
2

私のヒットの特定イベントが発生すると、私はRuby on RailsアプリケーションでOhmベースのオブジェクトの内容全体を期限切れにしたいと考えています。 Redis +を期限切れにして現在これを行うことは可能ですか?オブジェクトにはインデックスなどを含むオームを使用するときに複数のキーが関連付けられています。すべてが適切に消去されるようにしたいのですが、これが正式にサポートされているかどうか疑問でした。Ruby用にオブジェクト全体の内容をオームで期限切れにすることはできますか?

答えて

0

私はそれを担当するオームのための宝石を開発しました。いいえ、残念ながらohm-expire

+0

私はあなたの宝石を使用しようとしていますが、ユニークなインデックスに問題があります。一意のキーを持つレコードが期限切れになると、そのキーを使ってレコードを見つけることができますが、そのレコードの属性は空です。レコードを期限切れにして、期限切れ後にレコードを自動的に削除するにはどうすればよいですか?私が期限切れ後に同じ(削除された)ユニークキーを持つレコードを作成しようとしているとき、私はオーム一意例外を持っているからです。 –

+1

この問題も発生しています。これが実装上のバグかどうかはわかりません(したがって私はGitHubで問題を開いていません)か、Redisがこれを処理する方法です。より多くの研究が必要です! – Gav

+0

gem ohm-expireは放棄されており、現在は動作しません。この宝石はもう使わないでください。 – anothermh

2

は見てみましょう。このパズルを解く試みがいくつかありましたが、私が見たすべての人がオームのデータセットにアーティファクトを残しています。いずれもユニークな属性では動作しません。私の知る限りでは、すべてがオームのデータを一貫性のない状態にしています。

いくつかの例:例えば

はオームモデルが保存したときに、いくつかのフィールドがあるハッシュをRedisのために添加してもメンバーが追加しましたRedisが設定します。ハッシュまたはセット全体に対して有効期限を設定することはできますが、Redisハッシュの単一フィールドまたはセットの単一メンバーを期限切れにすることはできません。ハッシュまたはセット全体が期限切れになる。

主な問題は次のとおりです。これらのセットとハッシュが期限切れになった場合、モデル全体のインデックスまたは固有の属性の完全なレコードが失われます。したがって、Ohmが期限切れのミックスインを使用するときの共通の問題は、メインデータキーが期限切れになっても、findへの呼び出しがインデックスからのレコードを返しますが、ハッシュ値がゼロであることです。モデルに固有の属性が指定されている場合は、データ自体の期限が切れていても、例外を発生させずに期限切れの値を持つモデルに対してcreateを再度呼び出すことはできません。

Redisには有効期限コールバックはありません。したがって、特定のキーが期限切れになったときにハッシュフィールドの削除やメンバーの設定をトリガーする方法はありません。いくつかの人々は、ハッシュフィールドがやRedisの問題のリスト上のTTLを持つようにメンバーを設定できるように要求してきたが、それらはすべて(かなり合理的に)して答えsuch as thisで閉じられています

こんにちは、これはオリジナルのデザインで実装されません。

キーのネストされたタイプはありません。 集約データ型の単一フィールドには複雑な機能はありません。閉会

);理由ははるかに複雑であり、私はこれが優れているあなたを見ることができます何 客観的な方法がありませんので、多く は個人的な感情、好みや感性によってバイアスされています。報告してくれてありがとう。例えば

、ここオームのソースコード(ohm.rb, 651-699)からいくつかのコメントではない:のない操作が

# The base class for all your models. In order to better understand 
    # it, here is a semi-realtime explanation of the details involved 
    # when creating a User instance. 
    # 
    # Example: 
    # 
    # class User < Ohm::Model 
    #  attribute :name 
    #  index :name 
    # 
    #  attribute :email 
    #  unique :email 
    # 
    #  counter :points 
    # 
    #  set :posts, :Post 
    # end 
    # 
    # u = User.create(:name => "John", :email => "[email protected]") 
    # u.incr :points 
    # u.posts.add(Post.create) 
    # 
    # When you execute `User.create(...)`, you run the following Redis 
    # commands: 
    # 
    # # Generate an ID 
    # INCR User:id 
    # 
    # # Add the newly generated ID, (let's assume the ID is 1). 
    # SADD User:all 1 
    # 
    # # Store the unique index 
    # HSET User:uniques:email [email protected] 1 
    # 
    # # Store the name index 
    # SADD User:indices:name:John 1 
    # 
    # # Store the HASH 
    # HMSET User:1 name John email [email protected] 
    # 
    # Next we increment points: 
    # 
    # HINCR User:1:counters points 1 
    # 
    # And then we add a Post to the `posts` set. 
    # (For brevity, let's assume the Post created has an ID of 1). 
    # 
    # SADD User:1:posts 1 
    # 

しかし、人々は一般的にオームデータを期限切れにしようとする方法は、(このような非常に簡単なものですユニークまたはモデル全体の指数):要するに

Ohm.redis.expire(object.key, @expire) 
    Ohm.redis.expire("#{object.key}:_indices", @expire) 

、Redisの中のデータの有効期限のきめ細かな制御を取得するための最良の方法は、低レベルのINTを使用して、独自のストレージ方法論を設計することです例えば、redis-rb

1

よりもむしろのRedisを使用期限切れ、オームオブジェクトを期限切れにするためのより信頼性の高い方法は、別々の有効期限スレッドを有することによって、例えば、オブジェクトを直接調べて削除することです。これにより、モデルオブジェクトをチェックし、期限切れのオブジェクトを検出し、オームを介して削除を要求することができます。

オームは、Lua scriptを使用して原子的に削除を実行するため、オブジェクトに関連付けられたキーを正しくクリーンアップし、オブジェクトへの参照を他のオーム構造から削除します。オーム削除を使用すると、クリーンな有効期限のための最善の選択肢です。

このような設計を使用することで、信頼性、パフォーマンスをトレードオフする必要があるかもしれません:あなたのプログラムは、基本的に大規模なメモリアクセスおよび/またはRedisのクエリを伴うことが既知のすべてのオブジェクト、全体でガベージコレクションを実行します。期限切れの機能から支援を受けて、(相続またはミックスインを経由して)あなたのオームのモデルクラスの次の行に沿って実装することができ

def start_expiry_thread expiry_cycle 

    Thread.new { 

    while (true) do 

     MyOhmModel.all.each do |object| 
     object.delete if object.expired 
     end 

     sleep expiry_cycle 

    end 

    } 

end 

:ここ

は、クリーンアップスレッドが動作することができる方法の例です。オーム::タイムスタンプモジュール:

@max_life = 3600 

def expired    
    (time_since_update > @max_life) 
end 

def time_since_update 
    updated_secs = self.updated_at.to_i 
    (Time.now.to_i - updated_secs) 
end 

注:

  • テイクスレッド使用ロックを導入するときは、 が同じオブジェクトに同時に2つのスレッドで同時にアクセスしないようにするか、または単に 共有オブジェクトを避けて、有効期限切れスレッドを Redisに直接移動させないようにしてください。アプリケーション・プロセスが定期的にスケジュールされ、再起動されている場合

  • は、 代替は、他のワーカースレッドが開始される前に起動プロセス、 時にクリーンアップを実行することです。

  • はあなたの他の アプリケーションコードが優雅に有効期限を処理していることを確認します - 基本となるRedisの オブジェクトが アプリケーションコードによって保持された任意の同等のオブジェクトが無効になります意味し、消えてしまいます。バグが簡略化中にこっそりしている可能性がありので

  • 上、生産システムからのコードの簡易版です。

  • さらに一般的に言えば、本当にオームが必要であることを確認してください。キーバリューストアの上にリレーショナルレイヤーを追加することを検討している場合は、システムの技術的設計について懸命に考える必要があります。

関連する問題