ThinkPHP6/8 缓存系统与性能优化实战指南

在高并发Web应用开发中,缓存系统和性能优化是提升应用响应速度和用户体验的关键技术。本文将深入探讨ThinkPHP6/8框架中的缓存机制、Redis集成方案以及全面的性能优化策略。

缓存系统概述

ThinkPHP6/8支持多种缓存驱动,包括文件缓存、Redis缓存、Memcache缓存等。合理使用缓存可以显著减少数据库查询次数,提高应用性能。

缓存驱动对比

缓存类型 适用场景 优点 缺点
文件缓存 单机小型应用 简单易用,无需额外服务 性能较低,不支持分布式
Redis缓存 高并发分布式应用 性能高,支持数据结构 需要额外服务,内存消耗
Memcache缓存 简单键值缓存 性能好,内存效率高 功能相对简单

多缓存配置实现

1. 复合缓存配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?php
// config/cache.php
return [
// 缓存类型
'type' => 'complex',

// 默认缓存配置
'default' => [
'type' => 'file',
'path' => runtime_path() . 'cache/',
'prefix' => 'think_',
'expire' => 0,
'serialize' => [],
'tag_prefix' => 'tag:',
],

// 文件缓存
'file' => [
'type' => 'file',
'path' => runtime_path() . 'file_cache/',
'prefix' => 'file_',
'expire' => 3600,
],

// Redis缓存
'redis' => [
'type' => 'redis',
'host' => env('redis.host', '127.0.0.1'),
'port' => env('redis.port', 6379),
'password' => env('redis.password', ''),
'select' => env('redis.select', 0),
'timeout' => 3600,
'prefix' => 'think_redis_',
'tag_prefix' => 'tag:',
'serialize' => [],
// 连接池配置
'pool' => [
'min_connections' => 1,
'max_connections' => 10,
'connect_timeout' => 10.0,
'wait_timeout' => 3.0,
'heartbeat' => -1,
'max_idle_time' => 60.0,
],
],

// Redis集群配置
'redis_cluster' => [
'type' => 'redis',
'host' => [
'192.168.1.100:7000',
'192.168.1.100:7001',
'192.168.1.100:7002',
],
'password' => env('redis.password', ''),
'prefix' => 'cluster_',
'timeout' => 3600,
],
];

2. 缓存服务封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
<?php
namespace app\service;

use think\facade\Cache;
use think\facade\Log;
use think\exception\InvalidArgumentException;

/**
* 缓存服务类
* 提供统一的缓存操作接口和缓存策略管理
*/
class CacheService
{
// 缓存类型常量
const CACHE_FILE = 'file';
const CACHE_REDIS = 'redis';
const CACHE_CLUSTER = 'redis_cluster';

// 缓存时间常量
const TTL_MINUTE = 60;
const TTL_HOUR = 3600;
const TTL_DAY = 86400;
const TTL_WEEK = 604800;
const TTL_MONTH = 2592000;

/**
* 设置缓存
* @param string $key 缓存键
* @param mixed $value 缓存值
* @param int $ttl 过期时间(秒)
* @param string $store 缓存驱动
* @return bool
*/
public function set($key, $value, $ttl = self::TTL_HOUR, $store = self::CACHE_REDIS)
{
try {
$result = Cache::store($store)->set($key, $value, $ttl);

Log::info('缓存设置成功', [
'key' => $key,
'ttl' => $ttl,
'store' => $store,
'size' => strlen(serialize($value))
]);

return $result;
} catch (\Exception $e) {
Log::error('缓存设置失败', [
'key' => $key,
'error' => $e->getMessage(),
'store' => $store
]);
return false;
}
}

/**
* 获取缓存
* @param string $key 缓存键
* @param mixed $default 默认值
* @param string $store 缓存驱动
* @return mixed
*/
public function get($key, $default = null, $store = self::CACHE_REDIS)
{
try {
$value = Cache::store($store)->get($key, $default);

if ($value !== $default) {
Log::debug('缓存命中', [
'key' => $key,
'store' => $store
]);
} else {
Log::debug('缓存未命中', [
'key' => $key,
'store' => $store
]);
}

return $value;
} catch (\Exception $e) {
Log::error('缓存获取失败', [
'key' => $key,
'error' => $e->getMessage(),
'store' => $store
]);
return $default;
}
}

/**
* 记忆化缓存(如果不存在则执行回调并缓存结果)
* @param string $key 缓存键
* @param callable $callback 回调函数
* @param int $ttl 过期时间
* @param string $store 缓存驱动
* @return mixed
*/
public function remember($key, callable $callback, $ttl = self::TTL_HOUR, $store = self::CACHE_REDIS)
{
$value = $this->get($key, null, $store);

if ($value === null) {
$startTime = microtime(true);
$value = $callback();
$executeTime = microtime(true) - $startTime;

if ($value !== null) {
$this->set($key, $value, $ttl, $store);

Log::info('缓存回调执行', [
'key' => $key,
'execute_time' => round($executeTime * 1000, 2) . 'ms',
'store' => $store
]);
}
}

return $value;
}

/**
* 删除缓存
* @param string $key 缓存键
* @param string $store 缓存驱动
* @return bool
*/
public function delete($key, $store = self::CACHE_REDIS)
{
try {
$result = Cache::store($store)->delete($key);

Log::info('缓存删除', [
'key' => $key,
'store' => $store,
'result' => $result
]);

return $result;
} catch (\Exception $e) {
Log::error('缓存删除失败', [
'key' => $key,
'error' => $e->getMessage(),
'store' => $store
]);
return false;
}
}

/**
* 批量设置缓存
* @param array $data 键值对数组
* @param int $ttl 过期时间
* @param string $store 缓存驱动
* @return bool
*/
public function setMultiple(array $data, $ttl = self::TTL_HOUR, $store = self::CACHE_REDIS)
{
try {
$success = 0;
foreach ($data as $key => $value) {
if ($this->set($key, $value, $ttl, $store)) {
$success++;
}
}

Log::info('批量缓存设置', [
'total' => count($data),
'success' => $success,
'store' => $store
]);

return $success === count($data);
} catch (\Exception $e) {
Log::error('批量缓存设置失败', [
'error' => $e->getMessage(),
'store' => $store
]);
return false;
}
}

/**
* 缓存标签操作
* @param string|array $tags 标签
* @param string $store 缓存驱动
* @return \think\cache\TagSet
*/
public function tag($tags, $store = self::CACHE_REDIS)
{
return Cache::store($store)->tag($tags);
}

/**
* 清除标签缓存
* @param string|array $tags 标签
* @param string $store 缓存驱动
* @return bool
*/
public function clearTag($tags, $store = self::CACHE_REDIS)
{
try {
$result = Cache::store($store)->tag($tags)->clear();

Log::info('标签缓存清除', [
'tags' => $tags,
'store' => $store
]);

return $result;
} catch (\Exception $e) {
Log::error('标签缓存清除失败', [
'tags' => $tags,
'error' => $e->getMessage(),
'store' => $store
]);
return false;
}
}

/**
* 获取缓存统计信息
* @param string $store 缓存驱动
* @return array
*/
public function getStats($store = self::CACHE_REDIS)
{
try {
if ($store === self::CACHE_REDIS) {
$redis = Cache::store($store)->handler();
$info = $redis->info();

return [
'used_memory' => $info['used_memory_human'] ?? 'N/A',
'connected_clients' => $info['connected_clients'] ?? 0,
'total_commands_processed' => $info['total_commands_processed'] ?? 0,
'keyspace_hits' => $info['keyspace_hits'] ?? 0,
'keyspace_misses' => $info['keyspace_misses'] ?? 0,
'hit_rate' => $this->calculateHitRate($info),
];
}

return ['message' => '该缓存驱动不支持统计信息'];
} catch (\Exception $e) {
Log::error('获取缓存统计失败', [
'store' => $store,
'error' => $e->getMessage()
]);
return ['error' => $e->getMessage()];
}
}

/**
* 计算缓存命中率
* @param array $info Redis信息
* @return string
*/
private function calculateHitRate($info)
{
$hits = $info['keyspace_hits'] ?? 0;
$misses = $info['keyspace_misses'] ?? 0;
$total = $hits + $misses;

if ($total === 0) {
return '0%';
}

return round(($hits / $total) * 100, 2) . '%';
}
}

数据库缓存优化

1. 模型缓存实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<?php
namespace app\model;

use think\Model;
use app\service\CacheService;

/**
* 用户模型 - 带缓存功能
*/
class User extends Model
{
protected $cacheService;

public function __construct(array $data = [])
{
parent::__construct($data);
$this->cacheService = new CacheService();
}

/**
* 根据ID获取用户信息(带缓存)
* @param int $id 用户ID
* @return array|null
*/
public function getUserById($id)
{
$cacheKey = 'user:info:' . $id;

return $this->cacheService->remember($cacheKey, function() use ($id) {
return $this->where('id', $id)
->where('status', 1)
->field('id,username,nickname,email,avatar,create_time')
->find();
}, CacheService::TTL_HOUR);
}

/**
* 获取用户列表(带分页缓存)
* @param int $page 页码
* @param int $limit 每页数量
* @param array $where 查询条件
* @return array
*/
public function getUserList($page = 1, $limit = 20, $where = [])
{
$cacheKey = 'user:list:' . md5(serialize([$page, $limit, $where]));

return $this->cacheService->remember($cacheKey, function() use ($page, $limit, $where) {
$query = $this->where('status', 1);

// 动态添加查询条件
if (!empty($where['keyword'])) {
$query->where('username|nickname', 'like', '%' . $where['keyword'] . '%');
}

if (!empty($where['create_time'])) {
$query->whereBetweenTime('create_time', $where['create_time'][0], $where['create_time'][1]);
}

$list = $query->field('id,username,nickname,email,avatar,create_time')
->page($page, $limit)
->order('id desc')
->select();

$total = $query->count();

return [
'list' => $list,
'total' => $total,
'page' => $page,
'limit' => $limit
];
}, CacheService::TTL_MINUTE * 30);
}

/**
* 更新用户信息并清除相关缓存
* @param int $id 用户ID
* @param array $data 更新数据
* @return bool
*/
public function updateUser($id, $data)
{
$result = $this->where('id', $id)->update($data);

if ($result) {
// 清除用户相关缓存
$this->clearUserCache($id);
}

return $result;
}

/**
* 清除用户相关缓存
* @param int $id 用户ID
*/
private function clearUserCache($id)
{
// 清除用户信息缓存
$this->cacheService->delete('user:info:' . $id);

// 清除用户列表缓存(使用标签)
$this->cacheService->clearTag('user:list');
}
}

2. 查询缓存中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<?php
namespace app\middleware;

use app\service\CacheService;
use think\facade\Log;
use think\Response;

/**
* 查询缓存中间件
* 自动缓存GET请求的响应结果
*/
class QueryCacheMiddleware
{
protected $cacheService;

public function __construct()
{
$this->cacheService = new CacheService();
}

/**
* 处理请求
* @param \think\Request $request 请求对象
* @param \Closure $next 下一个中间件
* @return Response
*/
public function handle($request, \Closure $next): Response
{
// 只缓存GET请求
if (!$request->isGet()) {
return $next($request);
}

// 生成缓存键
$cacheKey = $this->generateCacheKey($request);

// 检查是否有缓存
$cachedResponse = $this->cacheService->get($cacheKey);

if ($cachedResponse !== null) {
Log::debug('查询缓存命中', [
'url' => $request->url(),
'cache_key' => $cacheKey
]);

return Response::create($cachedResponse['content'], 'html', 200, $cachedResponse['headers']);
}

// 执行请求
$startTime = microtime(true);
$response = $next($request);
$executeTime = microtime(true) - $startTime;

// 缓存响应结果(仅缓存成功的响应)
if ($response->getCode() === 200 && $this->shouldCache($request)) {
$cacheData = [
'content' => $response->getContent(),
'headers' => $response->getHeader(),
'cached_at' => time()
];

$ttl = $this->getCacheTtl($request);
$this->cacheService->set($cacheKey, $cacheData, $ttl);

Log::info('查询结果已缓存', [
'url' => $request->url(),
'cache_key' => $cacheKey,
'execute_time' => round($executeTime * 1000, 2) . 'ms',
'ttl' => $ttl
]);
}

return $response;
}

/**
* 生成缓存键
* @param \think\Request $request 请求对象
* @return string
*/
private function generateCacheKey($request)
{
$url = $request->url();
$params = $request->param();

// 排序参数确保一致性
ksort($params);

return 'query_cache:' . md5($url . serialize($params));
}

/**
* 判断是否应该缓存
* @param \think\Request $request 请求对象
* @return bool
*/
private function shouldCache($request)
{
// 不缓存的路径
$excludePaths = [
'/admin/login',
'/admin/logout',
'/api/upload',
];

$path = $request->pathinfo();

foreach ($excludePaths as $excludePath) {
if (strpos($path, $excludePath) === 0) {
return false;
}
}

return true;
}

/**
* 获取缓存时间
* @param \think\Request $request 请求对象
* @return int
*/
private function getCacheTtl($request)
{
$path = $request->pathinfo();

// 根据路径设置不同的缓存时间
if (strpos($path, '/api/') === 0) {
return CacheService::TTL_MINUTE * 5; // API接口缓存5分钟
}

if (strpos($path, '/admin/') === 0) {
return CacheService::TTL_MINUTE * 10; // 后台页面缓存10分钟
}

return CacheService::TTL_HOUR; // 默认缓存1小时
}
}

性能优化策略

1. 数据库连接池优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<?php
// config/database.php
return [
// 默认数据连接标识
'default' => env('database.driver', 'mysql'),

// 数据库连接信息
'connections' => [
'mysql' => [
// 数据库类型
'type' => env('database.type', 'mysql'),
// 服务器地址
'hostname' => env('database.hostname', '127.0.0.1'),
// 数据库名
'database' => env('database.database', ''),
// 用户名
'username' => env('database.username', 'root'),
// 密码
'password' => env('database.password', ''),
// 端口
'hostport' => env('database.hostport', '3306'),
// 数据库连接参数
'params' => [
// 使用长连接
\PDO::ATTR_PERSISTENT => true,
// 设置超时时间
\PDO::ATTR_TIMEOUT => 30,
// 设置字符集
\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4',
],
// 数据库编码默认采用utf8
'charset' => env('database.charset', 'utf8mb4'),
// 数据库表前缀
'prefix' => env('database.prefix', ''),
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 1,
// 数据库读写是否分离 主从式有效
'rw_separate' => true,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 是否需要断线重连
'break_reconnect' => true,
// 监听SQL
'trigger_sql' => env('app_debug', true),
// 开启字段缓存
'fields_cache' => true,
// 字段缓存路径
'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
// 连接池配置
'pool' => [
'enable' => true,
'min_connections' => 1,
'max_connections' => 20,
'connect_timeout' => 10.0,
'wait_timeout' => 3.0,
'heartbeat' => -1,
'max_idle_time' => 60.0,
],
],

// 从数据库配置
'mysql_slave' => [
'type' => 'mysql',
'hostname' => env('database.slave_hostname', '127.0.0.1'),
'database' => env('database.database', ''),
'username' => env('database.username', 'root'),
'password' => env('database.password', ''),
'hostport' => env('database.hostport', '3306'),
'params' => [
\PDO::ATTR_PERSISTENT => true,
\PDO::ATTR_TIMEOUT => 30,
],
'charset' => 'utf8mb4',
'prefix' => env('database.prefix', ''),
],
],
];

2. 性能监控服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
<?php
namespace app\service;

use think\facade\Db;
use think\facade\Log;
use app\service\CacheService;

/**
* 性能监控服务
*/
class PerformanceService
{
protected $cacheService;

public function __construct()
{
$this->cacheService = new CacheService();
}

/**
* 记录SQL执行性能
* @param string $sql SQL语句
* @param float $time 执行时间
* @param array $bind 绑定参数
*/
public function recordSqlPerformance($sql, $time, $bind = [])
{
// 慢查询阈值(毫秒)
$slowQueryThreshold = 1000;

if ($time > $slowQueryThreshold) {
Log::warning('慢查询检测', [
'sql' => $sql,
'time' => $time . 'ms',
'bind' => $bind,
'trace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5)
]);

// 记录慢查询统计
$this->recordSlowQuery($sql, $time);
}

// 记录SQL执行统计
$this->recordSqlStats($time);
}

/**
* 记录慢查询统计
* @param string $sql SQL语句
* @param float $time 执行时间
*/
private function recordSlowQuery($sql, $time)
{
$date = date('Y-m-d');
$cacheKey = 'slow_query_stats:' . $date;

$stats = $this->cacheService->get($cacheKey, []);

$sqlHash = md5($sql);
if (!isset($stats[$sqlHash])) {
$stats[$sqlHash] = [
'sql' => $sql,
'count' => 0,
'total_time' => 0,
'max_time' => 0,
'min_time' => PHP_INT_MAX,
];
}

$stats[$sqlHash]['count']++;
$stats[$sqlHash]['total_time'] += $time;
$stats[$sqlHash]['max_time'] = max($stats[$sqlHash]['max_time'], $time);
$stats[$sqlHash]['min_time'] = min($stats[$sqlHash]['min_time'], $time);

$this->cacheService->set($cacheKey, $stats, CacheService::TTL_DAY);
}

/**
* 记录SQL执行统计
* @param float $time 执行时间
*/
private function recordSqlStats($time)
{
$minute = date('Y-m-d H:i');
$cacheKey = 'sql_stats:' . $minute;

$stats = $this->cacheService->get($cacheKey, [
'count' => 0,
'total_time' => 0,
'max_time' => 0,
'min_time' => PHP_INT_MAX,
]);

$stats['count']++;
$stats['total_time'] += $time;
$stats['max_time'] = max($stats['max_time'], $time);
$stats['min_time'] = min($stats['min_time'], $time);
$stats['avg_time'] = $stats['total_time'] / $stats['count'];

$this->cacheService->set($cacheKey, $stats, CacheService::TTL_HOUR);
}

/**
* 获取性能统计报告
* @param string $date 日期
* @return array
*/
public function getPerformanceReport($date = null)
{
$date = $date ?: date('Y-m-d');

return [
'slow_queries' => $this->getSlowQueryStats($date),
'sql_stats' => $this->getSqlStats($date),
'cache_stats' => $this->cacheService->getStats(),
'system_stats' => $this->getSystemStats(),
];
}

/**
* 获取慢查询统计
* @param string $date 日期
* @return array
*/
private function getSlowQueryStats($date)
{
$cacheKey = 'slow_query_stats:' . $date;
$stats = $this->cacheService->get($cacheKey, []);

// 按执行次数排序
uasort($stats, function($a, $b) {
return $b['count'] - $a['count'];
});

return array_slice($stats, 0, 10); // 返回前10个
}

/**
* 获取SQL统计
* @param string $date 日期
* @return array
*/
private function getSqlStats($date)
{
$stats = [];

// 获取当天每小时的统计
for ($hour = 0; $hour < 24; $hour++) {
$hourKey = $date . ' ' . sprintf('%02d', $hour);
$hourStats = [];

// 获取该小时每分钟的统计
for ($minute = 0; $minute < 60; $minute++) {
$minuteKey = $hourKey . ':' . sprintf('%02d', $minute);
$cacheKey = 'sql_stats:' . $minuteKey;
$minuteStats = $this->cacheService->get($cacheKey, null);

if ($minuteStats) {
$hourStats[] = $minuteStats;
}
}

if (!empty($hourStats)) {
$stats[$hour] = [
'hour' => $hour,
'total_count' => array_sum(array_column($hourStats, 'count')),
'avg_time' => array_sum(array_column($hourStats, 'avg_time')) / count($hourStats),
'max_time' => max(array_column($hourStats, 'max_time')),
];
}
}

return $stats;
}

/**
* 获取系统统计
* @return array
*/
private function getSystemStats()
{
return [
'memory_usage' => memory_get_usage(true),
'memory_peak' => memory_get_peak_usage(true),
'load_average' => function_exists('sys_getloadavg') ? sys_getloadavg() : null,
'disk_free' => disk_free_space('.'),
'disk_total' => disk_total_space('.'),
];
}
}

缓存预热与更新策略

1. 缓存预热命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<?php
namespace app\command;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use app\service\CacheService;
use app\model\User;
use app\model\Article;

/**
* 缓存预热命令
*/
class CacheWarmupCommand extends Command
{
protected function configure()
{
$this->setName('cache:warmup')
->setDescription('缓存预热命令');
}

protected function execute(Input $input, Output $output)
{
$output->writeln('开始缓存预热...');

$cacheService = new CacheService();

// 预热用户数据
$this->warmupUserCache($cacheService, $output);

// 预热文章数据
$this->warmupArticleCache($cacheService, $output);

// 预热配置数据
$this->warmupConfigCache($cacheService, $output);

$output->writeln('缓存预热完成!');
}

/**
* 预热用户缓存
* @param CacheService $cacheService 缓存服务
* @param Output $output 输出对象
*/
private function warmupUserCache($cacheService, $output)
{
$output->writeln('预热用户缓存...');

$userModel = new User();

// 预热热门用户
$hotUsers = $userModel->where('status', 1)
->order('login_count desc')
->limit(100)
->select();

foreach ($hotUsers as $user) {
$cacheKey = 'user:info:' . $user->id;
$cacheService->set($cacheKey, $user->toArray(), CacheService::TTL_HOUR * 2);
}

$output->writeln('用户缓存预热完成,共预热 ' . count($hotUsers) . ' 个用户');
}

/**
* 预热文章缓存
* @param CacheService $cacheService 缓存服务
* @param Output $output 输出对象
*/
private function warmupArticleCache($cacheService, $output)
{
$output->writeln('预热文章缓存...');

$articleModel = new Article();

// 预热热门文章
$hotArticles = $articleModel->where('status', 1)
->order('view_count desc')
->limit(200)
->select();

foreach ($hotArticles as $article) {
$cacheKey = 'article:detail:' . $article->id;
$cacheService->set($cacheKey, $article->toArray(), CacheService::TTL_HOUR * 6);
}

$output->writeln('文章缓存预热完成,共预热 ' . count($hotArticles) . ' 篇文章');
}

/**
* 预热配置缓存
* @param CacheService $cacheService 缓存服务
* @param Output $output 输出对象
*/
private function warmupConfigCache($cacheService, $output)
{
$output->writeln('预热配置缓存...');

// 预热系统配置
$configs = [
'site_name' => '网站名称',
'site_keywords' => '网站关键词',
'site_description' => '网站描述',
'upload_max_size' => '10M',
'allowed_extensions' => 'jpg,jpeg,png,gif,pdf,doc,docx',
];

foreach ($configs as $key => $value) {
$cacheKey = 'config:' . $key;
$cacheService->set($cacheKey, $value, CacheService::TTL_DAY);
}

$output->writeln('配置缓存预热完成');
}
}

最佳实践总结

缓存策略最佳实践

  1. 分层缓存

    • L1缓存:进程内存缓存(APCu)
    • L2缓存:Redis缓存
    • L3缓存:文件缓存
  2. 缓存时间设置

    • 热点数据:1-6小时
    • 普通数据:30分钟-2小时
    • 配置数据:1天-1周
  3. 缓存更新策略

    • 主动更新:数据变更时立即更新缓存
    • 被动更新:缓存过期后重新加载
    • 定时更新:定期刷新缓存数据

性能优化最佳实践

  1. 数据库优化

    • 使用连接池减少连接开销
    • 开启查询缓存和字段缓存
    • 合理设置索引和查询优化
  2. 代码优化

    • 减少不必要的数据库查询
    • 使用批量操作替代循环操作
    • 合理使用懒加载和预加载
  3. 系统优化

    • 开启OPcache提升PHP性能
    • 使用CDN加速静态资源
    • 配置Gzip压缩减少传输大小

通过合理的缓存策略和性能优化,可以显著提升ThinkPHP应用的响应速度和并发处理能力。在实际项目中,需要根据具体的业务场景和性能要求,选择合适的缓存方案和优化策略。

本站由 提供部署服务