做项目时经常写这样的代码:
// 原生 Redis 写法 - 每次都要写这么一堆
$cacheKey = "user:profile:{$userId}";
$data = $redis->get($cacheKey);
if ($data === false) {
$data = $this->getUserFromDatabase($userId);
$redis->setex($cacheKey, 3600, json_encode($data));
} else {
$data = json_decode($data, true);
}
// Laravel Cache 写法 - 简单一些,但键名还是要手动拼接
$user = Cache::remember("user.profile.{$id}", 3600, function() use ($id) {
return getUserFromDatabase($id);
});
// 原生 Redis 写法 - 更复杂,要处理哪些有缓存哪些没有
$keys = [];
foreach ($ids as $id) {
$keys[] = "user:profile:{$id}";
}
$cached = $redis->mget($keys);
$result = [];
$missed = [];
foreach ($ids as $index => $id) {
if ($cached[$index] !== false) {
$result[$id] = json_decode($cached[$index], true);
} else {
$missed[] = $id;
}
}
if (!empty($missed)) {
$freshData = getUsersFromDatabase($missed);
foreach ($freshData as $id => $data) {
$result[$id] = $data;
$redis->setex("user:profile:{$id}", 3600, json_encode($data));
}
}
// Laravel Cache 写法 - 会产生N次数据库查询
$users = [];
foreach ($ids as $id) {
$users[$id] = Cache::remember("user.profile.{$id}", 3600, function() use ($id) {
return getUserFromDatabase($id); // 每个用户都查一次数据库
});
}
这种"先查缓存,没有就查数据库,然后存回缓存"的套路到处都是。单个数据还好,批量操作就比较繁琐了。
更麻烦的是缓存键的命名,团队里每个人都有自己的风格:
// 不同的命名风格
$key1 = "user_profile_{$id}"; // 下划线风格
$key2 = "user:profile:{$id}"; // 冒号风格
$key3 = "userProfile{$id}"; // 驼峰风格
$key4 = "cache_user_profile_{$id}"; // 带前缀
结果就是:
想着能不能写个工具简化一下,正好最近在用 Amazon Q AI,就让它帮忙写了个库。
现在变成这样:
// 原来需要7-8行代码,现在1行搞定
$user = kv_get('user.profile', ['id' => 123], function() {
return getUserFromDatabase(123); // 只有缓存没有时才执行
});
// 要获取多个用户的数据
$users = kv_get_multi('user.profile', [
['id' => 1],
['id' => 2],
['id' => 3]
], function($missedKeys) {
// 这个函数只会收到缓存中没有的键
// 比如缓存中有id=1的数据,这里就只会收到id=2,3
$data = [];
foreach ($missedKeys as $cacheKey) {
$params = $cacheKey->getParams();
$data[(string)$cacheKey] = getUserFromDatabase($params['id']);
}
return $data;
});
批量操作会把所有没有缓存的数据一次性查出来,避免了N+1查询问题。
// 不用再手写键名了
$key = kv_key('user.profile', ['id' => 123]);
// 自动生成: app:user:v1:profile:123
// 批量生成键名
$keys = kv_keys('user.profile', [
['id' => 1],
['id' => 2],
['id' => 3]
]);
kv_delete('user.profile', ['id' => 123]); // 删除这个用户的缓存
kv_delete_full('user.profile'); // 删除所有用户资料缓存
在配置文件里定义好模板:
// 配置文件
'user.profile' => [
'template' => 'profile:{id}', // 键的模板
'ttl' => 7200 // 缓存2小时
]
使用时只需要说明要什么数据:
$user = kv_get('user.profile', ['id' => 123], $callback);
// 库会自动生成标准的键名:app:user:v1:profile:123
这个键名的结构是:应用前缀:组名:版本:具体键
好处:
安装:
composer require asfop/cache-kv
配置:
use Asfop\CacheKV\Core\CacheKVFactory;
// 告诉库怎么连Redis
CacheKVFactory::configure(function() {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
return $redis;
});
使用:
// 获取数据
$data = kv_get('user.profile', ['id' => 123], function() {
return getUserFromDatabase(123);
});
// 删除缓存
kv_delete('user.profile', ['id' => 123]);
整个开发过程主要是和 Amazon Q 对话:
AI 的优势:
AI 的局限:
总的来说,AI 更像个很厉害的助手,能大大提高效率,但不能完全替代思考。
代码都开源了,觉得有用的话给个 star 😊
就是个解决重复代码的小工具,让缓存操作简单一些。没什么高深技术,但确实能提高开发效率。