import{_ as a,o as e,c as i,a2 as n}from"./chunks/framework.B-QBKwc1.js";const k=JSON.parse('{"title":"缓存架构设计","description":"项目采用两级缓存架构:请求级缓存(内存)+ 持久缓存(Cache 门面,默认 Redis),大幅减少数据库查询;数据变更时由 Observer 自动失效对应缓存,保证一致性。","frontmatter":{},"headers":[],"relativePath":"zh/architecture/cache.md","filePath":"zh/architecture/cache.md"}'),t={name:"zh/architecture/cache.md"};function p(l,s,d,c,h,r){return e(),i("div",null,[...s[0]||(s[0]=[n(`

4.8 缓存架构设计 ​

概述

项目采用两级缓存架构:请求级缓存(内存)+ 持久缓存(Cache 门面,默认 Redis),大幅减少数据库查询;数据变更时由 Observer 自动失效对应缓存,保证一致性。

两级缓存架构 ​

text
┌─────────────────────────────────────────────────────────┐
│ 第一级:请求级缓存(static 变量)                        │
│                                                         │
│ 生命周期:单次 HTTP 请求                                 │
│ 存储位置:PHP 内存(static $cache)                      │
│ 速度:极快(纳秒级)                                     │
│                                                         │
│ 同一请求内多次查询同一数据,只查一次库或缓存             │
└──────────────────────────┬──────────────────────────────┘
                           │ 未命中
                           ▼
┌─────────────────────────────────────────────────────────┐
│ 第二级:持久缓存(cache() 门面 / Redis)                 │
│                                                         │
│ 生命周期:跨请求复用                                     │
│ 存储位置:Redis(CACHE_STORE=redis,必需组件)            │
│ 速度:快(毫秒级)                                       │
│ 有效期:1 小时(3600 秒)                                │
│                                                         │
│ 跨请求复用,减少数据库压力                               │
└──────────────────────────┬──────────────────────────────┘
                           │ 未命中
                           ▼
┌─────────────────────────────────────────────────────────┐
│ 数据库查询                                               │
│                                                         │
│ 查询后同时写入两级缓存                                   │
└─────────────────────────────────────────────────────────┘

使用两级缓存的服务 ​

服务缓存键格式说明
DictCacheServicedict_{code}(前缀 dict_)字典项映射(CACHE_PREFIX = 'dict_',TTL 见 CACHE_TTL)
MenuService 等权限/菜单缓存角色权限列表(配合 Observer 失效)

缓存一致性:Observer 自动失效 ​

数据变更时由 Eloquent Observer 精确失效相关缓存(注册于 AppServiceProvider):

Observer监听模型触发动作
DictItemObserver字典项清除所属字典缓存(dict_{code})
MenuObserver菜单清除菜单/权限相关缓存
RoleMenuObserver角色-菜单关系清除角色权限缓存
text
字典项变更 → DictItemObserver → DictCacheService::clearCache(code) → 下次读取回源重建
菜单变更   → MenuObserver     → 权限缓存失效                  → 前端刷新菜单后生效

设计要点

缓存写入发生在"读取回源"时,失效只做 forget 不做主动重建——删除缓存比更新缓存更安全,避免并发下旧数据回写。

缓存驱动配置 ​

.env 配置:

ini
# Redis 缓存(项目默认,必需)
CACHE_STORE=redis
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=null        # 设置了 requirepass 时必须同步

不要改回 database/file 驱动

缓存清除 ​

php
// 清除指定字典缓存(Observer 已自动调用,此处为手动兜底)
DictCacheService::clearCache('gender');

// 清除所有字典缓存
DictCacheService::clearAllCache();

对应接口与命令:

text
GET /api/dict/refreshCache          刷新字典缓存(需认证)
php artisan dict:clear-cache        命令行清除字典缓存
php artisan config:clear            清除配置缓存(修改 .env 后)
php artisan cache:clear             清除全部应用缓存

Redis 使用全景 ​

用途使用方说明
JWT 双令牌会话JwtServicerefresh_token 存 Redis(支持踢下线、改密全端失效、一次性消费)
字典缓存DictCacheService两级缓存第二级
权限/菜单缓存Authenticate 中间件 + Observer角色权限列表
验证码CaptchaService图形验证码存取 + IP 限流
会话/队列Laravel 驱动SESSION_DRIVER / QUEUE_CONNECTION

连接验证:

bash
php artisan tinker --execute="try { \\Illuminate\\Support\\Facades\\Redis::setex('test:key', 10, 'ok'); echo 'OK: '.\\Illuminate\\Support\\Facades\\Redis::get('test:key'); } catch (\\Throwable \\$e) { echo \\$e->getMessage(); }"
# 输出 OK: ok 即连接正常
`,23)])])}const g=a(t,[["render",p]]);export{k as __pageData,g as default};