双Web服务器经ALB使用AWS ElastiCache Memcached存储PHP会话报错
排查与解决方案
1. 调整Memcached会话锁参数
多Web节点环境下,会话锁竞争是这类报错的核心原因,先检查PHP的Memcached会话锁配置:
- 打开
php.ini或站点根目录的.user.ini,确认以下参数:session.save_handler = memcached(确保会话存储驱动正确)- 增大锁等待时长:
memcached.sess_lock_wait = 2000(默认1000ms,竞争场景下容易超时) - 提高锁重试次数:
memcached.sess_lock_retries = 10(默认5次,增加重试降低失败概率) - 锁过期时间要长于会话超时:
memcached.sess_lock_expire = 1500(比如会话超时设为1440秒,锁过期留冗余)
- 修改后重启httpd服务生效。
2. 统一Web节点的Memcached客户端配置
两台服务器的PHP环境必须完全一致,否则会出现会话数据读写不兼容:
- 在两台服务器上执行
php -i | grep Memcached,对比扩展版本、编译参数,确保完全相同 - 统一会话序列化器:
session.serialize_handler = php_serialize(避免不同节点序列化规则不一致,同时规避旧序列化器的安全风险) - 确认会话键前缀一致:
memcached.sess_prefix = "php_sess_"(前缀不同会导致同一会话ID在不同节点生成的缓存键不一样)
3. 验证ALB会话粘性(可选缓解)
虽然共享Memcached不需要粘性,但暂时开启粘性可以减少跨节点的会话锁竞争,辅助排查:
- 登录AWS控制台,找到ALB对应的目标组,开启Cookie会话粘性,超时时间设置为和PHP会话超时一致(比如24分钟)
- 注意:这只是临时缓解,核心问题还是要解决锁配置或客户端一致性
4. 检查ElastiCache网络连通性
确保两台Web服务器都能正常访问ElastiCache集群:
- 在每台Web服务器上执行
telnet <ElastiCache集群端点> 11211,测试端口连通性,不通的话检查安全组规则(允许Web节点安全组访问ElastiCache的11211端口) - 查看CloudWatch的ElastiCache指标:
Connections(是否有连接失败)、GetMisses(是否异常升高),确认集群状态正常
5. 手动测试跨节点会话读写
直接验证两台服务器能否读写同一会话数据:
- 在服务器A运行测试脚本:
<?php session_save_path("tcp://<ElastiCache端点>:11211"); session_start(); $_SESSION['test_data'] = "来自服务器A的测试内容"; echo "会话ID:" . session_id(); ?>
- 记录输出的会话ID,在服务器B运行:
<?php session_save_path("tcp://<ElastiCache端点>:11211"); session_id("<刚才记录的会话ID>"); session_start(); var_dump($_SESSION['test_data']); ?>
- 如果服务器B读不到数据,说明序列化规则、前缀配置或扩展版本有差异,需要重新统一配置
6. 升级PHP Memcached扩展
旧版本的Memcached扩展存在分布式会话锁的bug,建议升级到最新稳定版:
- RHEL/CentOS系统:
yum update php-pecl-memcached - Ubuntu/Debian系统:
apt-get install --only-upgrade php-memcached - 升级后重启httpd:
systemctl restart httpd
内容的提问来源于stack exchange,提问作者Jeeva Jeeva
相关产品推荐
相关产品推荐

