Laravel使用Memcached时用户注销互相影响问题排查
问题:使用Memcached作为会话/缓存驱动时,用户注销会导致其他用户被强制注销
场景复现
- 修改
.env配置,将缓存与会话驱动切换为Memcached:CACHE_DRIVER=memcached SESSION_DRIVER=memcached - 执行配置与缓存清理命令:
php artisan config:clear php artisan cache:clear - 异常现象:User1在普通浏览器窗口登录,User2在隐私窗口登录,当User1执行注销操作时,User2也被自动强制注销;切换为
file驱动时,该问题消失,且此异常在生产服务器及不同设备上均可复现。
相关配置文件内容
config/session.php
'lifetime' => 120, 'expire_on_close' => false, 'encrypt' => false, 'files' => storage_path('framework/sessions'), 'store' => env('SESSION_STORE', null), 'lottery' => [2, 100], 'cookie' => env( 'SESSION_COOKIE', Str::slug(env('APP_NAME', 'laravel'), '_').'_session' ), 'path' => '/', 'domain' => env('SESSION_DOMAIN', null), 'secure' => env('SESSION_SECURE_COOKIE', true), 'http_only' => true, 'same_site' => 'none',
config/cache.php
'stores' => [ 'file' => [ 'driver' => 'file', 'path' => storage_path('framework/cache/data'), ], 'memcached' => [ 'driver' => 'memcached', 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 'sasl' => [ env('MEMCACHED_USERNAME'), env('MEMCACHED_PASSWORD'), ], 'options' => [ // Memcached::OPT_CONNECT_TIMEOUT => 2000, ], 'servers' => [ [ 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 'port' => env('MEMCACHED_PORT', 11211), 'weight' => 100, ], ], ], ], 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'),
原因分析
核心问题是会话与缓存共用了同一个Memcached存储实例,且注销逻辑误清除了全局缓存前缀下的所有数据:
- 当
SESSION_DRIVER设为memcached时,Laravel默认会复用缓存配置中的memcached存储,会话数据的键名前缀依赖于缓存的全局CACHE_PREFIX。 - 如果注销操作执行了
cache()->flush()这类清除整个缓存前缀下所有内容的逻辑,而非仅删除当前用户的会话键,就会把所有用户的会话数据一并清除,导致其他用户被强制注销。 - 使用
file驱动时,会话数据单独存在storage/framework/sessions目录的独立文件中,缓存数据则在storage/framework/cache/data,两者物理隔离,因此不会互相影响。
解决建议
- 为会话单独配置Memcached存储:在
config/cache.php中新增一个专用于会话的存储实例:'session_memcached' => [ 'driver' => 'memcached', 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 'sasl' => [ env('MEMCACHED_USERNAME'), env('MEMCACHED_PASSWORD'), ], 'options' => [], 'servers' => [ [ 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 'port' => env('MEMCACHED_PORT', 11211), 'weight' => 100, ], ], ], - 在
.env中设置SESSION_STORE=session_memcached,让会话使用独立存储,与普通缓存彻底隔离。 - 检查注销逻辑,确保仅删除当前用户的会话数据(比如使用框架原生的
auth()->logout(),而非手动清除整个缓存)。
内容的提问来源于stack exchange,提问作者Tamás Ficand
相关产品推荐
相关产品推荐

