ThinkPHP 面试精讲:缓存、Session 与队列高频面试题

在 PHP 开发者的面试中,ThinkPHP 作为国内最主流的框架之一,其缓存、Session 与队列机制几乎是中高级岗位的必考内容。面试官不仅关注你会不会用,更在意你是否理解底层原理、能否在复杂场景下做出合理的技术选型。本文梳理了这三类高频面试题,并给出深度解析,助你从容应对。

一、缓存机制:从驱动选择到缓存穿透

1. ThinkPHP 支持哪些缓存驱动?如何配置?

ThinkPHP 内置了多种缓存驱动,包括 File、Redis、Memcached、Memcache、Wincache、Sqlite 等。默认使用 File 驱动。配置位于 config/cache.php:

return [
    'default' => 'redis',
    'stores'  => [
        'file' => [
            'type'   => 'File',
            'path'   => '',
            'prefix' => '',
            'expire' => 0,
        ],
        'redis' => [
            'type'       => 'redis',
            'host'       => '127.0.0.1',
            'port'       => 6379,
            'password'   => '',
            'select'     => 0,
            'timeout'    => 0,
            'expire'     => 0,
            'persistent' => false,
            'prefix'     => '',
        ],
    ],
];

面试加分点:能说出 File 驱动在并发较高时存在读写锁竞争问题,生产环境推荐 Redis 或 Memcached。

2. 缓存操作常用方法有哪些?

use think\facade\Cache;

Cache::set('name', 'thinkphp', 3600);   // 写入并设置过期时间
Cache::get('name');                     // 读取
Cache::delete('name');                  // 删除
Cache::inc('views', 1);                 // 自增
Cache::dec('views', 1);                 // 自减
Cache::remember('key', function(){      // 闭包缓存,不存在时执行并写入
    return 'value';
}, 3600);
Cache::pull('name');                    // 读取并删除

3. 什么是缓存穿透、缓存击穿、缓存雪崩?ThinkPHP 中如何应对?

  • 缓存穿透:查询不存在的数据,请求绕过缓存直击数据库。解决方案:缓存空值(Cache::set('key', null, 60))或使用布隆过滤器。
  • 缓存击穿:热点 key 过期瞬间,大量请求涌入数据库。解决方案:使用 Cache::remember 配合互斥锁,或对热点数据设置永不过期并异步更新。
  • 缓存雪崩:大量 key 同时过期。解决方案:过期时间加随机值,例如 3600 + mt_rand(0, 600)。

面试官想听到的:你不仅知道概念,还能结合 ThinkPHP 的 remember 方法和 Redis 的 setnx 实现锁。

二、Session 机制:从存储驱动到分布式共享

1. ThinkPHP 的 Session 如何初始化?

在 ThinkPHP 6+ 中,Session 默认未开启。需要在中间件或应用初始化中调用:

// app/middleware.php 中全局开启
\think\middleware\SessionInit::class

配置位于 config/session.php,支持 file、cache、redis 等驱动。

2. Session 与 Cache 驱动的关系?

当 Session 驱动设为 cache 时,Session 数据实际存储在缓存中。配置示例:

return [
    'type'       => 'cache',
    'store'      => null,   // 使用默认缓存存储
    'expire'     => 1440,
    'prefix'     => 'session_',
];

若缓存默认驱动是 Redis,则 Session 自动存入 Redis,天然支持分布式共享。

3. 分布式环境下 Session 如何共享?

常见方案有三种:

  1. Redis 统一存储:所有节点连接同一 Redis,Session 驱动设为 cache 并指定 Redis 存储。这是 ThinkPHP 项目中最推荐的方式。
  2. 数据库存储:自定义 Session 驱动,将 Session 写入 MySQL,但性能较差。
  3. JWT 替代 Session:无状态令牌,不依赖服务端存储,适合前后端分离和微服务架构。

高频追问:Session 过期后 Redis 如何清理?答:Redis 的惰性删除 + 定期删除,也可通过 expire 设置 TTL 自动过期。

三、队列机制:从配置到失败重试

1. ThinkPHP 队列支持哪些驱动?

ThinkPHP 的队列组件 topthink/think-queue 支持 sync(同步)、database(数据库)、redis、beanstalkd、sqs 等驱动。安装:

composer require topthink/think-queue

配置文件 config/queue.php:

return [
    'default'     => 'redis',
    'connections' => [
        'redis' => [
            'type'       => 'redis',
            'queue'      => 'default',
            'host'       => '127.0.0.1',
            'port'       => 6379,
            'password'   => '',
            'select'     => 0,
            'timeout'    => 0,
            'persistent' => false,
        ],
    ],
];

2. 如何创建和推送队列任务?

// 创建任务类 app/job/OrderJob.php
namespace app\job;
use think\queue\Job;

class OrderJob
{
    public function fire(Job $job, $data)
    {
        // 处理业务逻辑
        if ($job->attempts() > 3) {
            $job->delete();
            return;
        }
        // 执行成功
        $job->delete();
    }
}

// 推送任务
use think\facade\Queue;
Queue::push(OrderJob::class, ['order_id' => 1], 'order_queue');
Queue::later(60, OrderJob::class, ['order_id' => 1], 'order_queue'); // 延迟60秒

3. 队列失败如何处理?

  • 重试机制:$job->attempts() 获取尝试次数,超过阈值可删除或重新入队。
  • 失败队列:配置 failed 表或 Redis 存储失败任务,通过 php think queue:failed 查看,php think queue:retry 重试。
  • 监听命令:php think queue:listen --queue order_queue 或 php think queue:work --daemon。

面试加分点:能对比 listen 和 work 的区别——listen 每次执行重新加载代码,适合开发;work 常驻内存,性能高但需重启生效,适合生产。

四、综合面试题演练

题目:一个电商秒杀场景,如何结合缓存、Session 和队列保证系统稳定?

参考回答:

  1. 用户登录后 Session 存入 Redis,实现多节点共享。
  2. 秒杀商品库存预热到 Redis,用 Cache::inc/dec 原子操作扣减,避免超卖。
  3. 扣减成功后推送队列异步生成订单,前端轮询或 WebSocket 通知结果。
  4. 对热点 key 设置随机过期时间,防止雪崩;对不存在商品缓存空值,防止穿透。
  5. 队列失败任务进入失败队列,人工补偿或定时重试。

结语

缓存、Session 与队列是 ThinkPHP 面试的“三座大山”,但背后的考点无非是数据一致性、并发安全、分布式扩展。建议在回答时先讲用法,再讲原理,最后结合场景给出方案,展现你的技术深度与工程思维。准备面试时,不妨亲手搭建一个 Redis + 队列 + Session 共享的 Demo,理解会更深刻。

未经允许不得转载:任鹏个人博客 » ThinkPHP 面试精讲:缓存、Session 与队列高频面试题

赞 (0) 打赏

评论 0

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

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

支付宝扫一扫打赏

微信扫一扫打赏