美文网首页PHP干货分享
Memcache如何存在数据量较大的value值

Memcache如何存在数据量较大的value值

作者: JUNE言JUNE语 | 来源:发表于2018-09-09 16:36 被阅读140次

说明:以下代码均在php56以上,Yii2框架环境下

有时候会遇到这种情况,明明设置了缓存,memcache什么的设置都ok,但是就是没有起效果,每次都是直接去数据库拿数据。这个时候就应该考虑,是不是数据量超出了memcache的最大限制【这个限制跟对应的memcache有关,可以通过配置重新编译更改大小,默认是1M】

一般情况下是不建议更改memcache的默认配置,原因1,你无法预测哪些少数数据量超大的数据,后续会继续增长到什么程度,有时候有些可能会到几十甚至上百M。原因2,可以参考这篇文章https://blog.csdn.net/u011386690/article/details/9316545

我们可以在程序层面去实现将缓存数据分片,以下提供一个demo


class CacheUtil
{
    const KEY_PREFIX = __CLASS__;

    const KEY_SLICE = 'slice';

    const KEY_INFO = 'info';

    /** @const int 当个value最大长度 1000kb 避免1M出现临界值无法set进去 */
    const MAX_LENGTH = 1024000;

    const KEY_COMPRESS = 'cacheCompress';

    const KEY_COMPRESS_LEVEL = 'cacheCompressLevel';

    private static $cache = null;

    /** @var $compress bool 是否开启压缩数据 针对分片 不分片默认使用缓存内部的压缩策略 */
    private static $compress = null;

    private static $compressLevel = null;

    private static function getCache()
    {
        return empty(self::$cache) ? self::$cache = \Yii::$app->getCache() : self::$cache;
    }

    public static function set($key, $value, $sliceFlag = false, $duration = null)
    {
        $cache = self::getCache();
        if (!$sliceFlag) {
            return $cache->set($key, $value, $duration);
        }
        $value = serialize($value);
        if (self::getCompress()) {
            $value = gzcompress($value, self::getCompressLevel());
        }
        $len = strlen($value);
        $size = ceil($len / self::MAX_LENGTH);
        $info = [
            'size' => $size,
            'compress' => self::getCompress(),
        ];
        $infoKey = self::getInfoKey($key);
        if (!$cache->set($infoKey, $info, $duration)) {
            return false;
        }
        // 分片存储
        for ($i = 0; $i < $size; $i++) {
            $sliceKey = self::getSliceKey($key, $i);
            $startIndex = $i * self::MAX_LENGTH;
            $_value = substr($value, $startIndex, self::MAX_LENGTH);
            if (!$cache->set($sliceKey, $_value, $duration)) {
                return false;
            }
            unset($_value);
        }
        return true;
    }

    public static function get($key, $sliceFlag = false)
    {
        $cache = self::getCache();
        if (!$sliceFlag) {
            // 不分片
            return $cache->get($key);
        }
        $infoKey = self::getInfoKey($key);
        $info = $cache->get($infoKey);
        if (empty($info)) {
            return false;
        }
        $value = '';
        $size = $info['size'];
        for ($i = 0; $i < $size; $i++) {
            $sliceKey = self::getSliceKey($key, $i);
            $_value = $cache->get($sliceKey);
            if (empty($_value)) {
                return false;
            }
            $value .= $_value;
            unset($_value);
        }
        if ($info['compress']) {
            $value = gzuncompress($value);
        }
        return unserialize($value);
    }

    private static function getInfoKey($key)
    {
        return self::KEY_PREFIX . $key . self::KEY_INFO;
    }

    private static function getSliceKey($key, $slice)
    {
        return self::KEY_PREFIX . $key . self::KEY_SLICE . $slice;
    }

    private static function getCompress()
    {
        if (self::$compress === null) {
            $params = \Yii::$app->params;
            if (isset($params[self::KEY_COMPRESS])) {
                self::$compress = $params[self::KEY_COMPRESS];
            } else {
                // 默认打开压缩
                self::$compress = true;
            }
        }
        return self::$compress;
    }

    private static function getCompressLevel()
    {
        if (self::$compressLevel === null) {
            $params = \Yii::$app->params;
            if (isset($params[self::KEY_COMPRESS_LEVEL])) {
                self::$compressLevel = $params[self::KEY_COMPRESS_LEVEL];
            } else {
                // 使用默认压缩级别
                self::$compressLevel = -1;
            }
        }
        return self::$compressLevel;
    }
}

代码大部分情况下是跟Yii2框架无关,除了获取缓存操作对象以及一些基本配置是使用yii2的写法以外,其他的都是通用的

相关文章

网友评论

    本文标题:Memcache如何存在数据量较大的value值

    本文链接:https://www.haomeiwen.com/subject/tuhdgftx.html