场景:项目中到处可见的key,没有统一管理,极其难维护。大佬同事实现了一个。
代码
如图,Redis.php 是对redis的二次封装,对redis key模块的强制校验,FillerKeyTrait.php 是对filler模块的key获取。主要原理是:对redis二次封装,统一调用入口,对key的获取通过 方法获取,对key根据配置的MODULES进行校验。
一.对redis二次封装
Redis.php代码
php"><?phpnamespace common\cache;use common\cache\keys\FillerKeyTrait;
use common\tools\Dingtalk;
use yii\helpers\Inflector;
use yii\redis\Connection;class Redis extends Connection
{const YEAR = 60*60*24*365;const DAY = 60*60*24;const MONTH = 60*60*24*31;use FillerKeyTrait;const checkCommands = ['set','setex','setnx','getset','hmset','hset','hsetnx','lset','psetex','setbit','incr','incrby','zincrby','incrbyfloat','hincrby','hincrbyfloat','decr','decrby','lpush','lpushx','rpush','rpushx','lset','linsert','sadd','zadd',];//均已空数组结尾const MODULES = ['filler' => [],];public function __call($name, $params){$redisCommand = strtoupper(Inflector::camel2words($name, false));if (in_array($redisCommand, self::checkCommands)) {if (!$this->checkKey($params[0])) {return;}}return parent::__call($name, $params);}public function get($key){$value = parent::get($key);$result = unserialize($value);
// if (!empty($value) && empty($result)) {
// $result = $value;
// }return $result;}public function set($key, $value, ...$options){if (!$this->checkKey($key)) {return;}$value = serialize($value);return parent::set($key, $value, $options);}public function setex($key, $seconds, $value){$value = serialize($value);return parent::setex($key, $seconds, $value);}public function setnx($key, $value){$value = serialize($value);return parent::setnx($key, $value);}public function hset($key, $field, $value){$value = serialize($value);return parent::hset($key, $field, $value);}public function hget($key, $field){$value = parent::hget($key, $field);$result = unserialize($value);return $result;}private function checkKey($key){try {//格式校验, 字母$arr = explode(':', $key);$count = count($arr);if ($count <= 2) {throw_info('缓存键名不合法');}if (strlen($key) > 64) {throw_info('缓存键名长度不能大于64位');}$modules = self::MODULES;foreach ($arr as $k => $v) {if (($k+1) == $count) {continue;}if (!isset($modules[$v])) {throw_info('缓存键名未配置');}$modules = $modules[$v];}return true;} catch (\Throwable $e) {if (YII_ENV != 'prod') {Dingtalk::sendMessageToRobot(SYSTEM_EXCEPTIONS, "{$key}缓存键名异常".$e->getMessage(), [GUOJUENENG_MOBILE]);}
// throw_info('系统繁忙,缓存异常');return false;}}
}
二、通过train 解耦和通过方法动态组建key
FillerKey.php
php"><?phpnamespace common\cache\keys;trait FillerKeyTrait
{public static function getFiller($platformType, $platformId, $day = ''){if (empty($day)) {$day = date('ymd');}return 'filler:' . $day . $platformId . ':' . $platformType;}
}
$key = Redis::getFiller(19,20,‘2023-12-12 09:12:23’);
三、yii2 redis初始化类直接调用 common\framework\Redis 或者读取后重启一个redis引用
php">return [//common\framework\Redis 'class' => 'yii\redis\Connection','hostname'=>'xxxxxxxx','port' => 6379,'database' => 1,'password' => 'xxxxxx',
// 'password' => '',
];
php">$goodsRedis = $redis;
$goodsRedis['database'] = 4;
$goodsRedis['class'] = 'common\framework\Redis';
四、全局入口
php">if (!function_exists('get_cache')) {/*** 获取商品专用redis对象* @return \common\framework\Redis*/function get_cache(){return \Yii::$app->goodsRedis;}
}