davafy 2016-01-05 16:25:18 9842次浏览 7条回复 1 1 0

在yii2使用memcache前根据文档配置好相应的参数,在使用memcache(非memcached)过程中会发现Yii::$app->cache->set('key','value');当这句话没有设置有效时间为多少秒时,可以正常获取到缓存中键为key的值,但表示此key不过期。当设置了有效时间时,Yii::$app->cache->set('key','value',60);比如60秒,就会出现取不到key对应的value值,网上和论坛里搜了搜,没有找到解决办法,也有很多phper遇到这类似的问题。所以特意去看了看底层代码,引用的memcache类为Yii2自带的yii\caching\MemCache,Yii::$app->cache->set('key','value')这句代码会自动调用memcache类下的setValue方法来设置缓存,所以问题也许就出现在这儿了。后面经过测试,发现这个方法最后一句return $this->useMemcached ? $this->_cache->set($key, $value, $expire) : $this->_cache->set($key, $value, 0, $expire)的问题,将这句代码改为return $this->useMemcached ? $this->_cache->set($key, $value, $expire) : $this->_cache->set($key, $value, 0, $duration)后,再测试发现问题已经解决,原因则是这句return代码里使用memcache时调用的$this->_cache->set($key, $value, 0, $expire),相当于$mem = new Memcache();$mem->set($key,$value,0,$expire);这里最关键的一点是:memcache要设置的时间的含义是有效时间为多少秒,memcached要设置的时间的含义是在哪一秒到期(等效于time()+$duration),所以发现问题所在之后将原来代码里的第二个$expire改成$duration问题就解决啦,因为发现是个系统bug,所以在论坛里来告诉大家一下,再有小伙伴遇到这个问题直接改一下这里就好,还有如果哪位小伙伴有精神可以告诉下yii2开发团队,下次yii升级的时候就可以修复这个bug了,暂时没修复时小伙伴们就照我上面说的改一下就可以用了。

觉得很赞
  • 回复于 2016-01-05 16:36 举报

    memcache::set() - You can also use Unix timestamp or a number of seconds starting from current time, but in the latter case the number of seconds may not exceed 2592000 (30 days).

    memcached::set() - The expiration time, defaults to 0. See Expiration Times for more info.

    Some storage commands involve sending an expiration value (relative to an item or to an operation requested by the client) to the server. In all such cases, the actual value sent may either be Unix time (number of seconds since January 1, 1970, as an integer), or a number of seconds starting from current time. In the latter case, this number of seconds may not exceed 606024*30 (number of seconds in 30 days); if the expiration value is larger than that, the server will consider it to be real Unix time value rather than an offset from current time.

    If the expiration value is 0 (the default), the item never expires (although it may be deleted from the server to make place for other items).

  • 回复于 2016-01-05 16:48 举报
    protected function setValue($key, $value, $duration)
    {
        $expire = $duration > 0 ? $duration + time() : 0;
    
        return $this->useMemcached ? $this->_cache->set($key, $value, $expire) : $this->_cache->set($key, $value, 0, $expire);
    }
    

    这是yii2本来的代码

  • 回复于 2016-01-05 16:51 举报

    我知道你的意思,这是yii2的一个bug,和你所说的set时间无关哦

  • 回复于 2016-01-05 17:07 举报

    刚又想了想,如果memcache和memcached的set都可以传时间戳的话,那么可能是我的memcache的版本的问题导致传时间戳进去不起作用,而只支持传秒数进去,但是网上看到很多phper都遇到这样的问题,所以我目前更支持把$expire改成$duration,这样不管是用memcache还是memcached都正确

  • 回复于 2016-01-11 17:04 举报

    应该是没bug的。memcache和memcached都可以是到期时间戳,传秒数,setValues会转成到期时间戳。

  • 回复于 2016-07-28 16:04 举报

    我最近也遇到这个问题, 我怀疑原因是, 过期时间被 yii的setValue函数设置成了 time()+$duration, 假如memcache服务器时间比本地时间快60s, 这时缓存就会失效。。

  • 回复于 2017-06-17 19:04 举报

    用memcache扩展的情况下确实是bug,我今天也碰到了,Yii还是当前最新版本2.0.12
    可能国外作者都用memcached扩展,所以没发现

您需要登录后才可以回复。登录 | 立即注册