ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

PHP 实战:用户登录接口频繁超时?从慢 SQL 到 Redis 缓存优化完整排查过程

PHP 实战:用户登录接口频繁超时?从慢 SQL 到 Redis 缓存优化完整排查过程 一、问题背景线上登录接口突然变慢最近维护一个 PHP 电商系统时运营反馈用户登录经常转圈有时候需要等待 5~10 秒才能进入后台。刚开始开发人员以为是服务器带宽问题但是查看服务器资源CPU30%左右内存40%左右网络正常但是 PHP-FPM 请求时间明显增加。接口POST /api/login.php平均响应正常200ms 异常 5000ms于是开始进行代码排查。二、问题定位发现登录接口查询过多原始登录代码?php $username $_POST[username]; $password $_POST[password]; $conn new mysqli( localhost, root, 123456, shop ); $sql select * from user where username$username; $result $conn-query($sql); $user $result-fetch_assoc(); if(md5($password)$user[password]){ echo 登录成功; }else{ echo 密码错误; } ?看起来没有问题。但是生产环境用户数量user表 300万执行select * from user where usernametest;发现Query_time: 3.8s原因用户名字段没有索引。三、数据库优化给用户表添加索引查看表结构show index from user;发现没有username索引添加ALTER TABLE user ADD INDEX idx_username(username);再次测试select * from user where usernametest;耗时优化前3.8秒优化后0.02秒响应速度提升接近100倍。四、第二个问题登录次数增加导致数据库压力优化 SQL 后发现高峰期数据库连接数 500原因每次登录都会查询数据库。流程用户输入账号密码 ↓ PHP查询MySQL ↓ 验证密码 ↓ 生成Token大量用户同时登录数据库压力增加。五、加入 Redis 缓存用户信息登录成功后把用户基础信息缓存。缓存结构user_login_用户ID { id:10001, username:admin, role:vip }Redis代码安装composer require predis/predis连接 Redisrequire vendor/autoload.php; $redis new Predis\Client([ host127.0.0.1, port6379 ]);六、优化后的登录逻辑完整代码?php require redis.php; $username$_POST[username]; $password$_POST[password]; //查询数据库 $sql select id,password from user where username? ; $stmt$pdo-prepare($sql); $stmt-execute([ $username ]); $user$stmt-fetch(); if(!$user){ exit(用户不存在); } //密码验证 if(md5($password)!$user[password]){ exit(密码错误); } //缓存用户信息 $keyuser_login:.$user[id]; $redis-setex( $key, 3600, json_encode([ id$user[id], username$username ]) ); echo json_encode([ code1, msg登录成功 ]); ?七、为什么 Redis 可以提升性能原流程请求 ↓ PHP ↓ MySQL ↓ 返回数据优化后请求 ↓ PHP ↓ Redis ↓ 快速返回Redis 内存读取0.001秒级MySQL10ms-100ms高并发情况下差距明显。八、增加登录防刷限制实际项目还有一个问题恶意用户不停请求登录接口。例如一分钟请求500次导致PHP进程增加 数据库压力增加解决Redis限制次数。代码?php $ip$_SERVER[REMOTE_ADDR]; $keylogin_error:$ip; $count$redis-get($key); if($count5){ exit(操作频繁请稍后再试); } ?失败次数增加$redis-incr($key); $redis-expire( $key, 600 );10分钟自动解除。九、生产环境常见错误1. 密码直接 MD5错误md5($password);问题MD5容易被破解。建议使用password_hash()例如$passwordHashpassword_hash( $password, PASSWORD_DEFAULT );验证password_verify( $password, $passwordHash );2. SQL直接拼接变量错误$sql select * from user where username$username ;存在SQL注入风险。应该$stmt$pdo-prepare( select * from user where username? );3. Redis缓存不过期错误redis-set( $key, $data );长期缓存可能导致数据不更新内存增长应该setex( $key, 3600, $data );十、上线前检查清单数据库✅ username增加索引✅ 慢SQL监控开启✅ 查询字段避免select *PHP✅ 使用PDO预处理✅ 开启OPcache✅ 合理设置PHP-FPM进程Redis✅ 设置过期时间✅ 监控内存✅ 设置最大连接数十一、优化结果优化前登录接口 5秒左右 数据库CPU 80%优化后登录接口 100ms以内 数据库CPU 30%同时支持5000 并发登录请求十二、总结PHP项目上线后接口变慢并不一定是服务器性能问题。很多时候真正原因来自SQL没有索引数据重复查询缓存设计不足缺少接口防刷机制一个稳定的登录系统需要MySQL负责数据存储 Redis负责高速访问 PHP负责业务处理通过数据库优化 Redis缓存 安全防护可以让普通 PHP 项目也具备支撑高并发业务的能力。
返回列表