ci4不支持自动sql查询缓存,必须手动集成redis实现缓存逻辑:统一在service层封装读写、设置合理过期时间、写后主动删除、规范key命名、监控命中率并配合读写分离部署。

CI4 本身不缓存查询结果,所有 SQL 执行都是实时打到数据库的。想靠框架自动缓存 SELECT 结果来减压,这条路走不通——必须自己动手加一层缓存逻辑。
用 Redis 缓存高频读结果
File 缓存太慢,扛不住并发;Redis 是 CI4 高并发场景下最实用的查询缓存方案。
- 安装并启用 Redis 驱动:确保
ext-redis已加载,配置app/Config/Cache.php中的redis处理器 - 对确定性查询(如按 ID 查用户、查配置项、地区列表)手动封装缓存读写:
先尝试$this->cache->get('user_123'),命中则直接返回;未命中则查库 +$this->cache->save('user_123', $data, 300)(单位秒) - 关键要设置合理过期时间:静态字典类可设 3600 秒,用户资料类建议 60–300 秒,避免脏数据
- 写操作后务必主动删除相关缓存(如更新用户昵称,删掉
user_123),不能只依赖过期
在 Service 层统一控制缓存边界
别把缓存逻辑散落在控制器或模型里,容易漏删、误用、难维护。
- 每个读接口对应一个缓存 key 模板,例如
"order_list_user_{uid}_page_{p}",用sprintf或strtr生成 - 把“查缓存 → 查库 → 写缓存 → 返回”封装成 Service 方法,比如
UserService::getCachedProfile(int $id) - 涉及关联查询(如订单+商品信息)可缓存整个结构化数组,不必拆成多 key,减少网络往返
- 缓存失效策略优先用主动删除,慎用延迟双删(先删后写)——CI4 没事务回滚钩子,失败时易残留脏缓存
避开缓存陷阱的几个硬规则
缓存不是万能胶,用错反而引发一致性问题或雪崩。
- 带登录态、权限判断、实时状态(如库存、在线人数)的查询,一律不缓存
- 分页列表类查询,不要缓存“第一页”,而应缓存“总条数 + 每页数据”,否则翻页错乱
- 从库读取的查询,如果已存在主从延迟,再加一层缓存会让“旧数据”停留更久,需评估业务容忍度
- 缓存 key 命名必须带版本号或哈希签名,例如
"v2:product_detail_{id}",方便全量刷新时批量 del
配合数据库连接优化一起生效
光加缓存不够,得让缓存真正拦住请求,而不是绕开它继续打库。
- 确保所有读操作都走你封装的缓存 Service,禁止在控制器里直接 new Database('read')→get()
- 关闭
DB_DEBUG = true,调试模式会强制重连+禁用连接复用,让缓存效果大打折扣 - 监控缓存命中率(可用 Redis
INFO stats的keyspace_hits / (keyspace_hits + keyspace_misses)),低于 70% 就该检查 key 设计或过期策略 - 搭配读写分离使用时,缓存应位于数据库之前——即“缓存 → 主/从库”,而不是“主库 → 缓存 → 从库”











