thinkphp本身不提供高可用能力,因其配置仅面向单实例(如数据库地址、缓存类型),缺乏集群、故障转移、跨节点会话同步等机制;高可用必须依赖外部架构:负载均衡(nginx/haproxy需健康检查)、redis集群托管session/cache、mysql主从+thinkphp读写分离配置、runtime目录禁用文件存储并设为只读。

ThinkPHP本身不是高可用系统,高可用靠的是架构设计,不是框架开关。单台服务器跑一个ThinkPHP实例,永远做不到高可用;必须配合负载均衡、无状态化、共享存储和故障隔离机制。
为什么不能直接用thinkphp自带配置实现高可用
ThinkPHP的.env或config/里没有「集群」「自动故障转移」「跨节点会话同步」这类配置项。它的配置只管单实例行为:数据库连接地址、缓存驱动类型、调试开关等。一旦你写死DB_HOST=192.168.1.10,加再多台PHP服务器也没用——所有实例都连同一个单点数据库,那个库一挂,全站瘫痪。
- 框架不处理进程管理、服务发现、健康检查,这些得由Nginx/HAProxy/K8s承担
-
runtime/目录默认写本地磁盘,多实例下日志、缓存、session互相覆盖或丢失 - 上传文件若保存在
public/uploads/,新请求打到另一台机器就找不到图片
nginx反向代理+upstream必须启用健康检查
只配upstream但不加health_check或check参数,等于没做高可用。Nginx默认不会主动探测后端PHP是否真能响应业务请求,它只看TCP端口通不通。PHP-FPM进程卡死、MySQL连接池耗尽、index.php报500错误,Nginx照样转发流量过去。
- 用
nginx-plus或开源版搭配nginx-module-vts+ 自定义/health接口(返回200且包含"status":"ok") - HAProxy更简单:
option httpchk GET /health+http-check expect status 200 - 避免用
max_fails=1 fail_timeout=10s这种宽松策略,生产建议max_fails=3 fail_timeout=30s
session和cache必须脱离本地文件系统
ThinkPHP默认把session存runtime/session/,cache存runtime/cache/,这是单机模式。多实例部署时,用户A第一次请求落在server1,登录态写进server1的本地文件;第二次请求被LB分到server2,server2根本读不到那个session,直接跳登录页。
- 强制改配置:
config/cache.php中'type' => 'redis',config/session.php中'type' => 'redis' - Redis要部署为集群或哨兵(Sentinel),别用单点Redis,否则Redis挂了,整个会话体系崩掉
- 别信
'type' => 'memcached'——Memcached无持久化、无主从,故障后session全丢,只适合临时缓存
数据库主从分离必须配合think-orm的读写分离配置
光搭好MySQL主从没用。ThinkPHP不会自动把SELECT发从库、INSERT/UPDATE发主库。必须显式配置,否则所有请求还是打在主库,从库纯闲置。
- 在
config/database.php中启用'deploy' => 1,并定义'read_host' => ['192.168.1.20', '192.168.1.21'],'write_host' => ['192.168.1.10'] - 注意从库延迟:实时性要求高的场景(如刚注册完立刻查用户信息),要用
Db::master()->table(...)->select()强制走主库 - 主从切换时,旧从库升主后,需手动更新配置或通过ZooKeeper/Consul动态下发,ThinkPHP不自动感知拓扑变更
最容易被忽略的其实是runtime/目录权限与清理策略。多实例共用NFS挂载点时,若某台机器的file_put_contents写一半崩溃,可能留下损坏的缓存文件,其他实例读取时报错;而定期rm -rf runtime/*又会导致所有实例缓存瞬间失效,引发数据库雪崩。真正的解法是彻底禁用文件类缓存,全部走Redis,并把runtime/设为只读挂载(除日志外)。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











