PHP 面试题:Session 与 Cookie 的关系及分布式 Session 解决方案

在 PHP 面试中,Session 与 Cookie 几乎是必考知识点。很多候选人能说出“Session 存在服务器,Cookie 存在浏览器”,但一旦追问“Session ID 是怎么传递的”“分布式环境下 Session 如何共享”,回答就开始模糊。本文从面试角度出发,系统梳理 Session 与 Cookie 的关系,并给出分布式 Session 的常见解决方案。

一、Session 与 Cookie 的本质区别

1. Cookie 是什么

Cookie 是服务器发送给浏览器并保存在客户端的一小段数据。浏览器后续请求同一域名时会自动携带它。Cookie 常见属性包括:

  • name=value:键值对
  • Expires/Max-Age:过期时间
  • Domain:生效域名
  • Path:生效路径
  • Secure:仅 HTTPS 传输
  • HttpOnly:禁止 JavaScript 读取,降低 XSS 窃取风险
  • SameSite:限制跨站请求携带,缓解 CSRF

PHP 中设置 Cookie:

setcookie('username', 'tom', time() + 3600, '/', '', false, true);

2. Session 是什么

Session 是服务器端保存用户状态的机制。PHP 默认通过 session_start() 开启会话,服务器生成一个唯一的 Session ID,并把用户数据保存在服务器端(默认文件存储)。Session ID 通常通过 Cookie 发给浏览器,浏览器下次请求时带回来,服务器据此找到对应会话数据。

session_start();
$_SESSION['user_id'] = 1001;

3. 两者的关系

一句话总结:Cookie 是 Session ID 的默认载体,Session 数据本身存在服务器。

  • 服务器调用 session_start() 时生成 PHPSESSID
  • 该 ID 通过 Set-Cookie 响应头写入浏览器
  • 浏览器后续请求自动携带 Cookie: PHPSESSID=xxx
  • 服务器根据该 ID 读取对应的 Session 文件

如果浏览器禁用了 Cookie,PHP 也支持通过 URL 参数传递 Session ID(session.use_trans_sid),但这种方式安全性差,容易泄露,生产环境不推荐。

二、常见面试追问

1. Session 和 Cookie 哪个更安全?

不能简单说谁更安全。Session 数据在服务器端,客户端只持有 ID,相对不易被篡改;但 Session ID 若被窃取,攻击者同样可以冒充用户。Cookie 若存储敏感信息且未加密,风险更高。实际安全取决于传输是否 HTTPS、是否设置 HttpOnly、是否防 CSRF 等。

2. 关闭浏览器后 Session 一定失效吗?

不一定。Session 的过期由服务器端 session.gc_maxlifetime 控制,而浏览器关闭后 Cookie 是否消失取决于 Cookie 是否设置了过期时间。默认 PHPSESSID 是会话 Cookie,关闭浏览器后消失,但服务器端 Session 文件可能仍然存在,直到被垃圾回收。

3. Session 和 Cookie 的容量限制

Cookie 一般单个域名下约 4KB,数量也有限制。Session 容量取决于服务器存储和配置,理论上可以更大,但也不建议存放大对象。

三、为什么需要分布式 Session

单机时代,Session 文件存在本机,问题不大。但在分布式架构中,用户请求可能被负载均衡转发到不同服务器:

  • 第一次请求落到 A 服务器,Session 写入 A
  • 第二次请求落到 B 服务器,B 找不到该 Session,用户被判定未登录

这就是典型的 Session 不一致问题。常见解决思路有以下几种。

四、分布式 Session 解决方案

1. Session 粘滞(Sticky Session)

通过负载均衡配置,让同一用户的请求始终落到同一台服务器。

  • 优点:实现简单,无需改代码
  • 缺点:服务器故障会丢失 Session;扩容缩容时重新分配麻烦;负载可能不均

适合小型系统或临时方案,不推荐作为长期架构。

2. Session 复制

多台服务器之间同步 Session 数据。

  • 优点:某台宕机后其他服务器仍有数据
  • 缺点:网络开销大,服务器越多同步成本越高,存在延迟

适合服务器数量很少的场景,规模一大就不现实。

3. 集中式存储(推荐)

把 Session 统一存到外部共享存储,所有应用服务器都访问同一份数据。常见选择:

  • Redis:性能高、支持过期、数据结构丰富,最常用
  • Memcached:简单高效,但数据易失
  • 数据库:持久化好,但性能一般,适合低并发

PHP 中可通过修改配置或实现 SessionHandlerInterface 接入 Redis:

ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://127.0.0.1:6379');
session_start();

也可以自定义处理器:

class RedisSessionHandler implements SessionHandlerInterface
{
    private $redis;

    public function __construct($redis)
    {
        $this->redis = $redis;
    }

    public function open($savePath, $sessionName): bool
    {
        return true;
    }

    public function close(): bool
    {
        return true;
    }

    public function read($id): string
    {
        return (string)$this->redis->get('session:' . $id);
    }

    public function write($id, $data): bool
    {
        return $this->redis->setex('session:' . $id, 1800, $data);
    }

    public function destroy($id): bool
    {
        return $this->redis->del('session:' . $id) > 0;
    }

    public function gc($maxLifetime): int
    {
        return 0;
    }
}
  • 优点:无状态化应用服务器,扩展性强,故障影响小
  • 缺点:引入额外组件,需要保证 Redis 高可用

4. JWT / Token 方案

把用户状态编码到 Token 中,由客户端保存,服务端不存 Session。

  • 优点:天然支持分布式,服务端无状态
  • 缺点:Token 撤销困难;不适合存储大量数据;需要处理续期和注销

适合 API、前后端分离场景,但不能完全替代传统 Session。

五、面试答题思路总结

回答这类问题时,可以按以下结构组织:

  1. 先说明 Cookie 与 Session 的本质区别和联系
  2. 指出 Session ID 默认通过 Cookie 传递
  3. 引出分布式场景下的 Session 不一致问题
  4. 对比粘滞、复制、集中存储、JWT 四种方案
  5. 给出推荐方案:Redis 集中存储 + 合理过期 + HTTPS + HttpOnly

这样回答既有概念,又有架构,还有落地细节,通常能给面试官留下较好的印象。

结语

Session 与 Cookie 不是对立关系,而是配合关系:Cookie 负责在客户端携带身份标识,Session 负责在服务端保存状态。理解这一点,再去看分布式 Session 的各种方案,思路就会清晰很多。实际项目中,Redis 集中存储是目前最主流、最平衡的选择,而 JWT 更适合无状态 API 场景。掌握这些,基本可以应对大多数 PHP 面试中的相关提问。

未经允许不得转载:任鹏个人博客 » PHP 面试题:Session 与 Cookie 的关系及分布式 Session 解决方案

赞 (0) 打赏

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏