Memcached实录PHP项目Yii2框架本地Docker-compose部署Memcached的坑/Yii2跨项目使用Memcached的key解决方案/亲测可用带源码建议收藏

Posted 小雨同学的服务器果然有问题

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Memcached实录PHP项目Yii2框架本地Docker-compose部署Memcached的坑/Yii2跨项目使用Memcached的key解决方案/亲测可用带源码建议收藏相关的知识,希望对你有一定的参考价值。

给出结论

docker部署的环境在docker内部,如果要在环境内访问,需要在项目配置中使用

	host.docker.internal

千万不能使用

	localhost

本地部署docker-compose文件

本配置包括了

拿走之后,部署之前,一定要改网段!!!

version: "3"
services:
  memcached:
    image: memcached:1.4.32
    ports:
      - "11211:11211"
    networks:
      web:
        ipv4_address: 172.25.0.9
  elastic:
    image: elasticsearch:6.7.0
#    image: elasticsearch:7.9.3
    ports:
      - "9200:9200"
    environment:
      - bootstrap.system_call_filter=false
#      - node.name=node-1
#      - cluster.initial_master_nodes=node-1
    volumes:
#      - /opt/docker/elasticsearch/data:/usr/share/elasticsearch/data
      - ../elasticsearch-local/data:/usr/share/elasticsearch/data
    networks:
      web:
        ipv4_address: 172.25.0.3
  kibana:
    image: kibana:6.7.0
#    image: kibana:7.9.3
    environment:
      - I18N_LOCALE=zh-CN
      - ELASTICSEARCH_HOSTS=http://172.25.0.3:9200
      - ELASTICSEARCH_URL=http://172.25.0.3:9200
    ports:
      - "5601:5601"
    networks:
      - web
  php:
    image: crunchgeek/php-fpm:7.0
    volumes:
      - ./yii_env.php:/var/www/yii_env.php
      - ./php.ini:/usr/local/etc/php/php.ini
      - ./:/var/www/html
    networks:
      - web
  web:
    image: nginx
    ports:
      - "8001-8009:8001-8009"
    volumes:
      - ./yii_env.php:/var/www/yii_env.php
      - ./:/var/www/html
      - ./default:/etc/nginx/conf.d/default.conf
      - ./localcerts:/etc/nginx/certs
    networks:
      - web

networks:
  web:
    ipam:
      driver: default
      config:
        - subnet: "172.25.0.0/16"

Yii2的Memcached相关配置

这里我继承原来的类,重写了两个方法,后面给出。

原来的类为yii\\caching\\MemCache

        'memcached' => [
            'class' => 'common\\components\\memcached\\Connection',
            'servers' => [
                [
                    'host' => 'host.docker.internal', //docker内配置
                    'port' => 11211,
                    'weight' => 100,
                ],
            ],
            'useMemcached' => true ,
        ],

YIi2下的跨项目使用Memcached的key的解决方案

Cache类中,框架内对key做了封装,源代码如下

    /**
     * Retrieves a value from cache with a specified key.
     * @param mixed $key a key identifying the cached value. This can be a simple string or
     * a complex data structure consisting of factors representing the key.
     * @return mixed the value stored in cache, false if the value is not in the cache, expired,
     * or the dependency associated with the cached data has changed.
     */
    public function get($key)
    {
        $key = $this->buildKey($key);
        $value = $this->getValue($key);
        if ($value === false || $this->serializer === false) {
            return $value;
        } elseif ($this->serializer === null) {
            $value = unserialize($value);
        } else {
            $value = call_user_func($this->serializer[1], $value);
        }
        if (is_array($value) && !($value[1] instanceof Dependency && $value[1]->isChanged($this))) {
            return $value[0];
        }

        return false;
    }


    /**
     * Stores a value identified by a key into cache.
     * If the cache already contains such a key, the existing value and
     * expiration time will be replaced with the new ones, respectively.
     *
     * @param mixed $key a key identifying the value to be cached. This can be a simple string or
     * a complex data structure consisting of factors representing the key.
     * @param mixed $value the value to be cached
     * @param int $duration default duration in seconds before the cache will expire. If not set,
     * default [[defaultDuration]] value is used.
     * @param Dependency $dependency dependency of the cached item. If the dependency changes,
     * the corresponding value in the cache will be invalidated when it is fetched via [[get()]].
     * This parameter is ignored if [[serializer]] is false.
     * @return bool whether the value is successfully stored into cache
     */
    public function set($key, $value, $duration = null, $dependency = null)
    {
        if ($duration === null) {
            $duration = $this->defaultDuration;
        }

        if ($dependency !== null && $this->serializer !== false) {
            $dependency->evaluateDependency($this);
        }
        if ($this->serializer === null) {
            $value = serialize([$value, $dependency]);
        } elseif ($this->serializer !== false) {
            $value = call_user_func($this->serializer[0], [$value, $dependency]);
        }
        $key = $this->buildKey($key);

        return $this->setValue($key, $value, $duration);
    }

其中,调用了buildKey($key),这样就会导致,实际写入的key并不是真正的key。

    /**
     * Builds a normalized cache key from a given key.
     *
     * If the given key is a string containing alphanumeric characters only and no more than 32 characters,
     * then the key will be returned back prefixed with [[keyPrefix]]. Otherwise, a normalized key
     * is generated by serializing the given key, applying MD5 hashing, and prefixing with [[keyPrefix]].
     *
     * @param mixed $key the key to be normalized
     * @return string the generated cache key
     */
    public function buildKey($key)
    {
        if (is_string($key)) {
            $key = ctype_alnum($key) && StringHelper::byteLength($key) <= 32 ? $key : md5($key);
        } else {
            if ($this->_igbinaryAvailable) {
                $serializedKey = igbinary_serialize($key);
            } else {
                $serializedKey = serialize($key);
            }

            $key = md5($serializedKey);
        }

        return $this->keyPrefix . $key;
    }

所以,我的做法是继承原有类,重写getset方法。

namespace common\\components\\memcached;

class Connection extends \\yii\\caching\\MemCache
{


    //跳过框架加密key,保证跨项目的缓存共用

    public function set($key, $value, $duration = 0, $dependency = null)
    {
        if(is_array($value)){
            $value = json_encode($value);
        }
        return $this->setValue($key, $value, $duration);
    }

    public function get($key)
    {
        $value =  $this->getValue($key);
        if(is_string($value) && json_decode($value,true)){
            $value = json_decode($value,true);
        }
        return $value;
    }

}

总结

  • 一定要牢记docker的访问范围
  • 多看源码,多思考

以上是关于Memcached实录PHP项目Yii2框架本地Docker-compose部署Memcached的坑/Yii2跨项目使用Memcached的key解决方案/亲测可用带源码建议收藏的主要内容,如果未能解决你的问题,请参考以下文章

注意区分Memcached与Memcache差别

用composer 安装yii2框架

源码安装LAMP环境+yii2框架

PHP精讲2021—Yii2框架项目中的缓存Cache组件实际应用以及分析问题思路

PHP精讲2021—Yii2框架项目中的缓存Cache组件实际应用以及分析问题思路

YII2.0版本框架利用composer安装