草庐IT

php - Redis - 按请求缓存流程

coder 2023-11-08 原文

我一直在网上搜索但没有成功找到答案,如果您根据用户请求进行缓存,应用程序的“FLOW”到底是如何工作的。

例如,最常用的处理“按请求”缓存的实现如下:

伪代码:

if(redis->hasKey('content')) {
       return content;
}
else {
       get_content_from_database();
       cache_content_in_redis();
       content_expire(10);

       return content;
}

比方说,使用上述逻辑的某个页面上突然有1000个请求。

逻辑上第一个请求命中 if 语句,将看到某个键下没有内容,将触发“else”部分并检索内容并缓存它。

我的问题:

其他请求会怎样?

第二个请求是否已经看到 key 下有内容并检索它?

如果触发它的请求仍在向 Redis 写入内容,会发生什么情况?

如果第二个请求也执行语句的“else”部分,是否会找到第二个write in place?

还是会跳过写入并返回数据库中的内容直到写入完成?

谁得到缓存的内容?

最佳答案

要回答你的问题(如果这个问题不应该以不同的方式解决,则无需讨论):你可以使用锁(如果你的应用程序在多个节点上,则使用分布式锁;如果你的应用程序在单个节点上运行,则使用 PHP 的信号量).

请注意,这是一个伪代码而不是实际的 PHP 实现:

$contentProvider->getData('my_key');

class ContentProvider
{
    private $lockHandler;

    public function getData($key)
    {
        $this->lockHandler->acquire($key);
        // Do the if/else part
        $this->lockHandler->release($key);

        return $data;
    }
}

您基本上需要为整个 if/else 部分进行阻塞。假设您有 1000 个请求。然后 1 个请求将获取锁,其余 (999) 将等待生成内容并将其存储在缓存中。之后剩下的 999 请求将随之而来。

问题是现在您有 1000 个请求顺序访问缓存的内容。不再有并行性,因为每次调用 getData 都会阻塞。

如果您在使用信号量的单个节点上运行,这可能不是什么大问题,但是当您需要切换到分布式锁时,这可能会显着影响您的性能(因为所有对 getData 的调用无论如何按顺序运行 - 即使它们在不同的节点上)。

话虽如此,我想指出一件事。上面的解决方案将保证缓存只生成一次,这似乎是一个可行的解决方案。但实际上并非如此。拥有缓存的全部意义在于速度快并且能够并发处理请求。有了锁,这是不可能的。

因此,如果遇到这种情况的可能性很大,那么根据请求进行缓 stub 本不是一种选择,您需要找到另一种解决方案。但是,如果这种情况不太可能发生 - 只需保留原始代码(没有锁)。即使您不时多次生成相同的数据,也可能不会成为问题。

关于php - Redis - 按请求缓存流程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49892591/

有关php - Redis - 按请求缓存流程的更多相关文章

  1. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  2. ruby - 如何在 Ubuntu 中清除 Ruby Phusion Passenger 的缓存? - 2

    我试过重新启动apache,缓存的页面仍然出现,所以一定有一个文件夹在某个地方。我没有“公共(public)/缓存”,那么我还应该查看哪些其他地方?是否有一个URL标志也可以触发此效果? 最佳答案 您需要触摸一个文件才能清除phusion,例如:touch/webapps/mycook/tmp/restart.txt参见docs 关于ruby-如何在Ubuntu中清除RubyPhusionPassenger的缓存?,我们在StackOverflow上找到一个类似的问题:

  3. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  4. ruby-on-rails - Ruby on Rails 计数器缓存错误 - 2

    尝试在我的RoR应用程序中实现计数器缓存列时出现错误Unknownkey(s):counter_cache。我在这个问题中实现了模型关联:Modelassociationquestion这是我的迁移:classAddVideoVotesCountToVideos0Video.reset_column_informationVideo.find(:all).eachdo|p|p.update_attributes:videos_votes_count,p.video_votes.lengthendenddefself.downremove_column:videos,:video_vot

  5. ruby - HTTP 请求中的用户代理,Ruby - 2

    我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)

  6. ruby-on-rails - 获取并发布相同匹配项的请求 - 2

    在我的路线文件中我有:match'graphs/(:id(/:action))'=>'graphs#(:action)'如果是GET请求(工作)或POST请求(不工作),我想匹配它我知道我可以使用以下方法在资源中声明POST请求:post'/'=>:show,:on=>:member但是我怎样才能为比赛做到这一点呢?谢谢。 最佳答案 如果你同时想要POST和GETmatch'graphs/(:id(/:action))'=>'graphs#(:action)',:via=>[:get,:post]编辑默认值可以设置如下match'g

  7. ruby-on-rails - 如何在 ActionController::TestCase 请求中设置内容类型 - 2

    我试图像这样在我的测试用例中执行获取:request.env['CONTENT_TYPE']='application/json'get:index,:application_name=>"Heka"虽然,它失败了:ActionView::MissingTemplate:Missingtemplatealarm_events/indexwith{:handlers=>[:builder,:haml,:erb,:rjs,:rhtml,:rxml],:locale=>[:en,:en],:formats=>[:html]尽管在我的Controller中我有:respond_to:html,

  8. ruby-on-rails - 这个 C 和 PHP 程序员如何学习 Ruby 和 Rails? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它

  9. ruby - 如何测试 (rspec) 花费太长时间的 http 请求? - 2

    如果使用rspec请求花费的时间太长,我该如何测试行为?我正在考虑使用线程来模拟这个:describe"Test"doit"shouldtimeoutiftherequesttakestoolong"dolambda{thread1=Thread.new{#net::httprequesttogoogle.com}thread2=Thread.new{sleep(xxseconds)}thread1.jointhread2.join}.shouldraise_errorendend我想确保在第一次发出请求后,另一个线程“启动”,在这种情况下只是休眠xx秒。然后我应该期望请求超时,因为执

  10. ruby - Sinatra 路由中定义的全局变量是否在请求之间共享? - 2

    假设我有:get'/'do$random=Random.rand()response.body=$randomend如果我每秒有数千个请求到达/,$random是否会被共享并“泄漏”到上下文之外,或者它会像getblock的“本地”变量一样?我想如果它是在get'/'do的上下文之外定义的,它确实会被共享,但我想知道在ruby​​中是否有我不知道的$机制。 最佳答案 ThispartoftheSinatraREADMEaboutscopeisalwayshelpfultoread但是,如果您只需要为请求保留变量,那么我认为我建议使用

随机推荐