这个问题类似于a question asked about java ,但我在 php 中执行此操作,因此我认为它不符合重复项的条件。
我想要一种在调用此函数时生成确定性 key 的方法。该功能应该像读取缓存一样运行。如果 key 存在,则检索数据。如果不是,则调用存储数据的函数,然后返回它。
这是我所拥有的并且它有效,但我不确定它是否安全以及它是否足够确定性甚至足够独特,因为我对这些主题的理解绝对为 0。
// $call = function being called $args = arguments to that function
// $force = force cache to bypassed, then updated
public function cachedCall($call,$args = [],$force = false)
{
$cache = \App\App::getInstance()->cache;
$key = md5($call) . md5(serialize($args));
$res = $cache->get($key);
if($res === -1 || $force){
$res = call_user_func_array([$this,$call],$args);
if(!empty($res) && $res !== false && $res !== 0 && !is_null($res)){
$cache->set($key,$res,0); //never set empty data in the cache.
}
}
return $res;
}
我的问题只与计算 key 的第三行有关。您可以看到它是由被调用函数和提供给该函数的参数计算得出的。我在某些情况下发生过碰撞。我正在寻找改进它的方法,使其更有用,并且哈希值一致但不太可能发生冲突。第三个参数可以忽略,因为它只是一种强制绕过缓存的方法。
如何调用此函数的示例:
$data = $db->cachedCall('getUserByEmail',[$this->email],true);
$data = $db->cachedCall('getCell',['SELECT id FROM foobar WHERE foo=:bar',[':bar'=>55]]);
如果可能的话,我想保证 key 同时具有一致的长度。
最佳答案
这是因为键在不同的实例中可能是相同的,例如当调用方法 cachedCall 时具有相同的参数。正如我想象的那样,您应该为每个实例共享相同的 memcached 服务器,这就是缓存冲突的原因。
正如我所读,变量 $call 将与代码的任何其他部分共享有限的值,因为它将包含类的方法名称,该类包含方法 < strong="">cachedCall,这意味着两个不同的调用很容易共享这个值。
此外,您可以使用空参数数组调用此方法。
因此,很容易在两个不同的实例中调用相同的方法:
cachedCall('methodX', array()); <- From instance A
cachedCall('methodX', array()); <- From instance B
这会将此内容存储在相同的memcached key
在方法内部,以某种方式考虑实例名称。例如,您可以使用当前 url 作为 key 或域名的一部分(取决于您的情况):
$key = md5($call) . md5(serialize($args)) . md5($_SERVER['HTTP_HOST']);
$key = md5($call) . md5(serialize($args)) . md5($_SERVER['REQUEST_URI']);
您可以在上面看到两个示例,说明如何根据您的实例更改memcached 键。
关于php - Memcached key 生成 从参数到函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36171591/
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了