简介
本文件面向 DouPHP 的数据缓存实现,聚焦以下目标:
- Redis 缓存配置(连接、集群、持久化)与接入建议
- Memcached/Memcache 使用方法(服务器配置、连接池、错误处理)
- 缓存数据结构设计(键命名规范、数据类型选择、序列化格式)
- 缓存操作最佳实践(批量、事务、并发控制)
- 监控与调试(命中率、性能分析、内存使用)
- 提供可直接落地的代码示例与配置模板路径
说明:仓库中内置的缓存适配层基于 Memcache/Memcached 适配器;Redis 未提供现成适配器。文档在“Redis”部分给出通用接入建议与最佳实践,便于后续扩展。
项目结构
DouPHP 将缓存能力以“统一接口 + 多后端适配器”的方式组织,并通过配置构建器管理多主机/角色(主从)拓扑。核心位置如下:
- 统一入口与连接管理:plugin/alipay/sdk/lotusphp_runtime/Cache/CacheHandle.php
- 适配器接口与实现:plugin/alipay/sdk/lotusphp_runtime/Cache/Adapter/*
- 配置构建器:plugin/alipay/sdk/lotusphp_runtime/Cache/CacheConfigBuilder.php
- 框架配置中心:core/foundation/configuration/Config.php
- 系统常量与模块清单:config/system.php
- 应用基础配置:config/config.php
- 云服务 API 配置(与缓存无关但属于全局配置):config/cloud.php
- 后台缓存清理服务:admin/service/cache/CacheClearService.php
graph TB
A["业务代码"] --> B["LtCacheHandle<br/>统一入口"]
B --> C["LtCacheConnectionManager<br/>连接管理"]
C --> D["LtCacheAdapterMemcache<br/>Memcache 适配器"]
C --> E["LtCacheAdapterMemcached<br/>Memcached 适配器"]
B --> F["LtCacheConfigBuilder<br/>配置构建器"]
A --> G["Config<br/>配置中心"]
A --> H["系统常量/模块清单<br/>config/system.php"]
核心组件
- LtCacheHandle:对外暴露 add/get/update/del 等统一方法,内部通过连接管理器获取具体适配器与连接资源。
- LtCacheAdapter(接口):定义 connect/add/del/get/update 契约,屏蔽底层差异。
- LtCacheAdapterMemcache / LtCacheAdapterMemcached:分别封装 memcache_connect 与 Memcached 扩展调用,并统一 key 前缀为“表名-键”。
- LtCacheConfigBuilder:支持按 group/node/role 维度注册多个主机,自动推导默认配置,便于主从与多节点部署。
- Config:集中式配置读取与设置,支持点语法访问,便于在不同环境切换缓存后端。
架构总览
下图展示一次典型缓存写入流程:业务调用统一入口,经由连接管理器选择适配器与连接,最终落到具体后端(Memcache/Memcached)。
sequenceDiagram
participant App as "业务代码"
participant Handle as "LtCacheHandle"
participant CM as "LtCacheConnectionManager"
participant Adapter as "LtCacheAdapter*"
participant Backend as "Memcache/Memcached"
App->>Handle : add(key, value, ttl, table)
Handle->>CM : getConnection(group, node, role)
CM-->>Handle : {adapter, connectionResource}
Handle->>Adapter : add(table-key, value, ttl, table, conn)
Adapter->>Backend : set(table-key, value, ttl)
Backend-->>Adapter : result
Adapter-->>Handle : result
Handle-->>App : result
详细组件分析
统一入口 LtCacheHandle
- 职责:封装连接初始化与适配器调用,屏蔽组/节点/角色选择细节。
- 关键点:initConnection 通过连接管理器获取 adapter 与 connectionResource;所有写读操作均委托给适配器。
- 可扩展性:新增后端只需实现 LtCacheAdapter 并在连接管理器中注册即可。
适配器接口与实现
- 接口契约:connect/add/del/get/update,参数包含 key、value、ttl、table、connectionResource。
- Memcache 适配器:使用 memcache_connect 建立连接,key 拼接规则为“table-key”,TTL 直接透传。
- Memcached 适配器:使用 Memcached 扩展,addServer 添加节点,同样采用“table-key”键空间隔离。
classDiagram
class LtCacheAdapter {
+connect(hostConf)
+add(key, value, ttl, table, connectionResource)
+del(key, table, connectionResource)
+get(key, table, connectionResource)
+update(key, value, ttl, table, connectionResource)
}
class LtCacheAdapterMemcache {
+connect(hostConf)
+add(...)
+del(...)
+get(...)
+update(...)
-getRealKey(table, key)
}
class LtCacheAdapterMemcached {
+connect(hostConf)
+add(...)
+del(...)
+get(...)
+update(...)
-getRealKey(table, key)
}
LtCacheAdapter <|.. LtCacheAdapterMemcache
LtCacheAdapter <|.. LtCacheAdapterMemcached
配置构建器 LtCacheConfigBuilder
- 能力:支持 group/node/role 三维注册主机,自动推导默认配置(同 role 首个 host、slave 继承 master 默认等)。
- 用途:用于多实例、读写分离或分片场景的配置组装。
配置中心 Config
- 能力:集中加载、设置、读取配置,支持点语法与批量操作。
- 用途:承载缓存后端类型、主机列表、超时、序列化策略等配置项的统一存取。
系统常量与模块清单
- system.php:定义前台固定模块、小程序内建模块、保留 URL 段等系统级常量,与缓存无直接耦合,但影响路由与页面生成时的缓存策略。
应用基础配置
- config.php:数据库与应用密钥等基础常量,可作为缓存相关常量(如 DOU_DEBUG)的参考位置。
云服务 API 配置
- cloud.php:仅用于云服务 API 地址与下载白名单,与缓存无关,但体现全局配置的组织方式。
后台缓存清理服务
- CacheClearService:提供删除缓存目录的能力,便于本地或运维清理编译/模板缓存。
依赖关系分析
- 低耦合:业务仅依赖 LtCacheHandle,不感知后端差异。
- 可插拔:新增 Redis 或其他后端仅需实现 LtCacheAdapter,并在连接管理器中注册。
- 配置驱动:通过 LtCacheConfigBuilder 与 Config 统一管理后端拓扑与运行时参数。
graph LR
Handle["LtCacheHandle"] --> |选择| AdapterI["LtCacheAdapter(接口)"]
AdapterI --> M1["Memcache 适配器"]
AdapterI --> M2["Memcached 适配器"]
Handle --> CFG["LtCacheConfigBuilder"]
Handle --> CONF["Config"]
性能考量
- 键空间隔离:适配器统一以“表名-键”作为真实 key,避免跨模块冲突。
- TTL 控制:合理设置过期时间,降低热点数据长期驻留带来的内存压力。
- 连接复用:同一进程内尽量复用连接资源,减少握手开销。
- 序列化体积:优先使用轻量序列化(如 JSON),避免大对象频繁落盘/落缓存。
- 批量操作:对读多写少的聚合数据,考虑一次性拉取并缓存为集合,减少多次往返。
- 冷启动预热:关键字典类数据可在服务启动时预热,降低首访延迟。
故障排查指南
- 连接失败
- 检查主机与端口配置是否正确,确认防火墙与网络可达。
- 对于 Memcached,确认已正确 addServer;对于 Memcache,确认 memcache_connect 成功。
- 键冲突
- 确保“表名-键”命名唯一,避免不同模块共用相同表名前缀导致覆盖。
- 数据不一致
- 更新后及时失效旧键或采用版本号策略;对强一致场景,谨慎使用缓存。
- 内存溢出
- 限制单条值大小,启用合理的 TTL;监控后端内存使用率。
- 命中率低
- 调整缓存粒度与 TTL;对热点数据做聚合缓存;避免过短 TTL 导致频繁重建。
- 清理缓存
- 使用后台提供的缓存清理服务清理本地缓存目录。
结论
DouPHP 当前内置的缓存适配层围绕 Memcache/Memcached 提供稳定可靠的键值存储能力,并通过统一入口与配置构建器实现了良好的可扩展性与可维护性。若需引入 Redis,可按现有适配器模式新增 Redis 适配器,并利用配置构建器进行集群与持久化策略管理。
附录:配置与使用模板
Redis 缓存配置(建议方案)
- 连接设置
- 单机:host/port/password/timeout/dbindex
- 集群:nodes 列表、cluster 模式开关、密码、连接池大小
- 持久化选项
- RDB:save 规则、rdbcompression、rdbchecksum
- AOF:appendonly、appendfsync 策略、aofrewrite 参数
- 接入步骤
- 新增 Redis 适配器实现 LtCacheAdapter
- 在连接管理器中注册 Redis 节点与角色
- 通过 LtCacheConfigBuilder 配置多节点与默认 host
- 在 Config 中集中管理 redis.* 配置项
Memcached 使用方法
- 服务器配置
- 主机列表、端口、是否启用压缩、超时时间
- 连接池管理
- 复用连接资源,避免频繁创建销毁
- 根据 QPS 调整连接数与线程数
- 错误处理
- 捕获连接异常与写入失败,降级到直读数据库或返回兜底数据
- 记录告警日志,便于快速定位
缓存数据结构设计指南
- 键命名规范
- 统一采用“表名-业务标识-子键”三段式,例如:product-123-detail
- 避免特殊字符,保持可读性与可扫描性
- 数据类型选择
- 标量:字符串/数字(JSON 或原始值)
- 集合:Hash/Set/List/ZSet(根据查询模式选择)
- 复杂对象:JSON 序列化,控制体积
- 序列化格式
- 推荐 JSON;如需高性能且跨语言,可选 MessagePack 或 CBOR
- 版本化字段,兼容未来结构变更
缓存操作最佳实践
- 批量操作
- 读:批量查询后合并为集合缓存,减少多次 IO
- 写:批量失效或批量更新,注意幂等与一致性
- 事务处理
- 缓存与数据库非强一致,必要时采用“先更新库,再删缓存”或“延迟双删”
- 对关键写路径增加重试与补偿机制
- 并发控制
- 使用分布式锁保护热点键重建,避免雪崩
- 设置合理 TTL 与随机抖动,降低同时过期风险
监控与调试工具
- 命中率统计
- 在适配器层埋点,统计 get/hits/misses 比率
- 结合指标平台(如 Prometheus)采集与告警
- 性能分析
- 记录单次请求的缓存耗时分布,识别慢键
- 对热点键进行采样分析
- 内存使用监控
- 监控后端内存占用、最大内存、淘汰策略命中情况
- 定期巡检大键与长尾键
代码示例与配置模板(路径指引)
- 统一入口调用示例
- 参考:CacheHandle.php:23-45
- Memcache 适配器示例
- 参考:CacheAdapterMemcache.php:10-28
- Memcached 适配器示例
- 参考:CacheAdapterMemcached.php:12-30
- 配置构建器示例
- 参考:CacheConfigBuilder.php:14-36
- 配置中心使用示例
- 参考:Config.php:44-80
- 系统常量与模块清单
- 参考:system.php:11-34
- 应用基础配置
- 参考:config.php:15-53
- 云服务 API 配置
- 参考:cloud.php:26-33
- 后台缓存清理
- 参考:CacheClearService.php:35-44