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;
}
所以,我的做法是继承原有类,重写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的访问范围
- 多看源码,多思考
以上是关于Memcached实录PHP项目Yii2框架本地Docker-compose部署Memcached的坑/Yii2跨项目使用Memcached的key解决方案/亲测可用带源码建议收藏的主要内容,如果未能解决你的问题,请参考以下文章
PHP精讲2021—Yii2框架项目中的缓存Cache组件实际应用以及分析问题思路