面试题答案
一键面试1. 选择合适的缓存数据结构
- 哈希表(Hash Table):适用于根据课程 ID 快速查找课程资料。它具有 O(1) 的平均时间复杂度,能快速定位缓存中的数据。例如在 Python 中可使用字典(dict),在 Java 中可使用 HashMap 来实现。
- 链表(Linked List):若需要考虑数据的访问顺序,如实现最近最少使用(LRU)缓存淘汰策略时,链表可发挥作用。双向链表能方便地在 O(1) 时间内删除和移动节点。结合哈希表和双向链表可以高效实现 LRU 缓存,像 Java 中的 LinkedHashMap 就支持这种特性。
- 缓存数组:对于一些固定顺序或范围查询的场景,比如按照课程分类批量获取课程资料,数组结构可以按照分类索引来存储,直接通过索引获取数据,查询时间复杂度为 O(1) 。
2. 缓存分片
- 按课程 ID 取模分片:将课程 ID 对缓存服务器数量进行取模运算,根据结果将数据分配到不同的缓存服务器上。例如,有 5 台缓存服务器,课程 ID 为 123 的课程资料就被分配到
123 % 5 = 3
号服务器上。这样可以实现数据的均匀分布,每个服务器承担大致相同的负载。 - 一致性哈希分片:为每个缓存服务器在哈希环上分配一个位置,对课程 ID 进行哈希运算后,将其映射到哈希环上。数据会被存储在顺时针方向遇到的第一个缓存服务器上。当增加或减少缓存服务器时,只有少量数据需要迁移,能更好地应对服务器的动态变化,降低缓存雪崩的风险。例如在分布式缓存系统 Memcached 中,一致性哈希是一种常用的分片方式。
3. 缓存预热
- 批量加载:在系统启动前,通过脚本从数据库中批量读取热门课程资料,并加载到缓存中。可以按照课程热度排序,优先加载热度高的课程。例如,在 Python 中可以使用
pymysql
连接数据库,读取热门课程数据,再使用redis - py
将数据写入 Redis 缓存。 - 后台异步预热:在系统启动后,通过后台任务(如使用 Celery 等任务队列)逐渐将课程资料加载到缓存中。这种方式不影响系统的正常启动,但可能在预热完成前,部分请求仍需从数据库读取数据。例如,设置定时任务每 5 分钟加载一定数量的课程资料到缓存,直到所有热门课程都被预热。
- 结合用户行为预热:分析历史用户行为数据,了解不同时间段、不同用户群体的课程访问模式。在相应的时间段或针对特定用户群体,提前预热他们可能访问的课程资料。比如,根据历史数据发现每天晚上 8 - 10 点是学生访问编程课程的高峰期,在每天晚上 7 点左右就提前预热相关编程课程资料。