0
点赞
收藏
分享

微信扫一扫

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


给出结论

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

host.docker.internal

千万不能使用

localhost

本地部署docker-compose文件

本配置包括了


  • nginx
  • php
  • elasticsearch
  • kibana

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

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;
}

所以,我的做法是继承原有类,重写​​get​​​和​​set​​方法。

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的访问范围
  • 多看源码,多思考


举报

相关推荐

0 条评论