首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可以在Ruby的Ohm中终止整个对象的内容吗?

可以在Ruby的Ohm中终止整个对象的内容吗?
EN

Stack Overflow用户
提问于 2012-04-05 02:00:52
回答 3查看 1.4K关注 0票数 2

一旦我的特定事件命中,我希望能够终止我的Ruby on Rails应用程序中基于Ohm的对象的全部内容。目前有没有可能用Redis + expire来做这件事呢?在使用Ohm时,对象有多个键与之关联,包括索引等。我想确保所有东西都被正确清理--这就是为什么我想知道是否有官方支持的方法来做到这一点。

EN

回答 3

Stack Overflow用户

发布于 2013-07-21 07:41:43

不幸的是,没有。已经有过几次尝试来解决这个难题,但我看到的每一次都在欧姆数据集中留下了伪像。它们中没有一个具有独特的属性,而且据我所知,它们都使欧姆数据处于不一致的状态。

下面是一些例子:

例如,当一个Ohm模型保存时,有几个字段被添加到Redis散列中,还有一些成员被添加到Redis集合中。虽然您可以设置整个散列或集合的过期时间,但不能使Redis散列的单个字段或集合的单个成员过期。整个散列或集合都会过期。

主要问题是:如果这些集合和散列过期,您将丢失模型上的整个索引或唯一属性的完整记录。因此,使用任何Ohm过期混合时的一个常见问题是,即使主数据密钥过期,对find的调用仍将返回索引中的记录,但哈希值为空。如果在模型中指定了唯一的属性,那么即使数据本身已经过期,也不能再用过期的值在该模型上调用create而不引发异常。

Redis中没有过期回调,因此无法在特定key过期时触发移除散列字段或设置成员。一些人要求允许哈希域或集合成员在Redis问题列表上有TTL,但他们都(相当合理地)用answers such as this关闭了

嗨,这不会由原始设计实现:

键中没有嵌套类型。聚合数据类型的单个字段中没有复杂功能。推理要复杂得多,而且有很多个人感觉、偏好和情感的偏见,所以没有客观的方法可以证明这是更好的;)

关门了。感谢您的报道。

例如,以下是来自Ohm源代码(ohm.rb, 651-699)的一些注释:

代码语言:javascript
复制
  # 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 => "foo@bar.com")
  #   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 foo@bar.com 1
  #
  #   # Store the name index
  #   SADD User:indices:name:John 1
  #
  #   # Store the HASH
  #   HMSET User:1 name John email foo@bar.com
  #
  # 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
  #

但是人们通常尝试终止欧姆数据的方法是这样的简单得多(不操纵唯一项或模型范围的索引):

代码语言:javascript
复制
  Ohm.redis.expire(object.key, @expire)
  Ohm.redis.expire("#{object.key}:_indices", @expire)

总之,在Redis中对数据过期进行细粒度控制的最好方法是使用低级接口(如redis-rb )设计自己的存储方法。

票数 2
EN

Stack Overflow用户

发布于 2014-09-12 06:12:53

与使用Redis终止对象相比,更可靠的终止Ohm对象的方法是直接检查和删除对象,例如,通过单独的到期线程。这可以检查模型对象,检测那些已经过期的对象,并通过Ohm请求删除。

Ohm使用Lua script自动执行删除,这会正确地清除与对象关联的任何键,并从其他Ohm结构中删除对该对象的引用。使用欧姆删除是干净过期的最佳选择。

通过使用这样的设计,您可能需要牺牲性能来换取可靠性:您的程序本质上将跨所有已知对象执行垃圾收集,这可能涉及大量的内存访问和/或Redis查询。

下面是一个清理线程如何工作的示例:

代码语言:javascript
复制
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

其中,过期函数可以在Ohm模型类中按照以下行实现(通过继承或混合),并得到Ohm::Timestamp模块的支持:

代码语言:javascript
复制
@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

备注:

  • 在引入线程时要小心-使用锁定来防止两个线程同时访问同一对象,或者简单地避免共享对象并将到期线程直接转到Redis。
  • 如果您的应用程序进程有定期的定时重新启动,则另一种选择是在启动过程中执行清理,然后启动任何其他工作线程。
  • 确保您的其他应用程序代码处理优雅地到期-底层Redis对象将消失,这意味着应用程序代码持有的任何等效对象都将无效。
  • 上面是生产系统中代码的简化版本。因此,bug可能在simplification.
  • Also过程中悄悄潜入,更一般地说:请检查您是否真的需要Ohm。如果您正在考虑在键值存储之上添加相当于关系层的东西,那么您应该认真考虑系统的技术设计。
票数 1
EN

Stack Overflow用户

发布于 2012-05-16 21:07:49

我已经为Ohm开发了一个gem来处理它。

看一下:ohm-expire

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10016719

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档