【问题标题】:Catalyst Model cache dbix callsCatalyst 模型缓存 dbix 调用
【发布时间】:2017-02-12 07:44:19
【问题描述】:

我正在编写一个Catalyst 应用程序,我有一个Model,它代表一个值不会改变的小设置表。我不想每次都查询数据库,而是缓存响应。在我使用DBIx::Class 的模型中,我确实看到了这个DBIx::Class::Cursor::Cached,它看起来像是一个选项。

但是,我最终做的是使用Memoize 在我的模型中缓存返回值。我对此解决方案有两个问题:

  1. Catalyst 模型是否只创建一次,然后在应用程序的整个生命周期内使用?还是$c->model()每次都新建一个Model类?

  2. 如果我使用 fastcgi 运行我的应用程序并且有 6 个线程,这意味着我的应用程序的每个线程都将获得自己的模型类,并且必须进行查询并拥有 6 个单独的缓存,对吗?

这是一个糟糕的解决方案吗?我应该做点别的吗?

【问题讨论】:

    标签: perl caching catalyst dbix-class


    【解决方案1】:

    Catalyst 模型是否只创建一次,然后在应用程序的整个生命周期中使用?还是$c->model()每次都新建一个Model类?

    这取决于您对模型的实现。如果您的模型中有ACCEPT_CONTEXT 方法,Catalyst 将在您每次调用$c->model() 时创建一个新对象。如果没有,它将在应用程序启动期间实例化一次。这在 Initialization 下的Catalyst::Manual::Internals 中有记录。

    YAPC::EU 2016 in Cluj,Catalyst 的当前维护者 John Napiorkowski 进行了(远程)关于 Catalyst 的讨论,从from about 53 minutes into the talk 开始解释了这一方面。整件事以及他的其他演讲都值得一看。

    如果我使用 fastcgi 运行我的应用程序并且有 6 个线程,这意味着我的应用程序的每个线程都将获得自己的模型类,并且必须进行查询并拥有 6 个单独的缓存,对吗?

    我不确定那个。我相信它启动一次然后分叉。所以它会创建一个实例并将其复制到分支。


    为您的方法使用 DBIx::Class::Cursor::Cached 看起来可行。如果您需要 DBIx::Class ResultSet 对象,那很好。如果没有,您可以将结果作为惰性属性附加到您的模型中。它可能看起来像这样:

    package My::Model;
    use Mooose;
    use My::DB::Schema;
    extends 'Catalyst::Model';
    
    has stuff => (
        is => 'ro',
        isa => 'HashRef',
        traits => ['Hash'],
        handles => {
            has_stuff => 'exists',
            get_stuff => 'get',
            # ...
        },
        lazy => 1,
        builder => '_build_stuff',
    );
    
    sub _build_stuff {
        my ($self) = @_;
    
        # get stuff from the DB here, convert it to a config hash
        # or whatever you need and store it in our stuff attribute
    
        # that works well if your config looks something like this:
    
        # {
        #     color => 'red',
        #     price => 13.37,
        #     things => [ qw/ foo bar baz / ],
        #     # ...
        # }
    
        # you can then use the Hash trait on your attribute to access it
    }
    
    1;
    

    这样它会在你第一次使用它时加载它,然后你就完成了。它只会存储在对象中。

    如果您想调查这是否真的有效并且不进行更多查询,您可以使用DBIC_TRACE=1 环境变量打开 DBIC's tracing output。它会将丰富多彩的查询转储到您的 Catalyst 日志中。


    或者,CHI 非常适合构建事物的缓存,尽管在这里可能有点过头了。

    【讨论】:

    • 感谢您的详尽回答!我喜欢在启动时将其从数据库中取出然后使用它的方法——这正是我所寻找的。我想知道的一个问题是,你认为这比使用 Memoize 更好吗?还是 Memoize 是一个糟糕的解决方案?因为本质上它以非常相似的方式工作,因为它只是构建一个哈希。我想我更喜欢您的解决方案,因为它在构建对象后全部缓存,只是对您的想法感到好奇。
    • @src 我认为这不是一个糟糕的解决方案,而且总是有不止一种方法可以做到这一点,但它是为不同的目的而设计的。我会用最简单的方法。使用 Moose 属性是非常自然的。它不添加依赖项,并且易于使用。我经常使用这种方法处理来自文件的数据,而且效果很好。
    • 太棒了。这就是我要做的。谢谢!
    猜你喜欢
    • 2011-07-09
    • 1970-01-01
    • 2012-02-13
    • 1970-01-01
    • 2012-05-27
    • 1970-01-01
    • 2013-01-19
    • 2015-05-25
    • 1970-01-01
    相关资源
    最近更新 更多