面试题答案
一键面试设计思路
- 缓存粒度控制:
- 按请求类型:对于不同权限用户的资源获取请求,由于权限不同,数据差异大,应按用户权限级别和请求路径分别缓存。例如,管理员权限的用户请求
/admin/resources
和普通用户请求/user/resources
,缓存应分开管理。 - 按分页数据:分页数据请求,缓存粒度可以按页码和每页数量来控制。如
/data?page=1&size=10
和/data?page=2&size=10
应分别缓存,这样可以精准控制缓存内容,避免大量重复数据缓存。
- 按请求类型:对于不同权限用户的资源获取请求,由于权限不同,数据差异大,应按用户权限级别和请求路径分别缓存。例如,管理员权限的用户请求
- 缓存依赖关系:
- 链式请求:对于依赖其他请求结果的链式请求,建立依赖关系图谱。例如,请求B依赖请求A的结果,那么先缓存请求A的结果,当请求B发起时,检查请求A的缓存是否存在且有效。若存在,则基于请求A的缓存结果发起请求B,并缓存请求B的结果,同时记录B对A的依赖关系。
- 全局缓存依赖:可以使用一个缓存管理器来维护所有请求的依赖关系,方便在缓存更新或失效时进行级联处理。
- 缓存一致性:
- 缓存更新策略:当数据发生变化时,通过HTTP响应头的
ETag
或Last - Modified
字段来判断缓存是否失效。若数据更新,服务器返回新的ETag
或修改后的Last - Modified
时间,客户端据此更新缓存。 - 主动失效:对于一些重要数据的变更,如用户权限修改,服务器可以主动通知客户端缓存失效,客户端收到通知后清除相关缓存。
- 缓存更新策略:当数据发生变化时,通过HTTP响应头的
关键实现要点
- 缓存存储:
- 使用浏览器的
localStorage
或sessionStorage
存储缓存数据,适合较小规模且不频繁更新的数据。对于大规模数据,可以考虑使用服务端缓存,如Redis。 - 设计一个缓存数据结构,例如
{requestUrl: {data: '缓存数据', timestamp: '缓存时间', dependencies: ['依赖的请求URL列表']}}
。
- 使用浏览器的
- 拦截器:
- 在Angular应用中,使用HTTP拦截器来处理缓存逻辑。在请求发出前,拦截器检查缓存是否存在且有效,若有效则直接返回缓存数据;在响应返回后,拦截器根据响应头信息更新缓存。
- 依赖管理:
- 在缓存数据结构中记录依赖关系,当某个请求的缓存失效时,根据依赖关系找到相关依赖的缓存并进行处理,如标记为无效或直接删除。
性能优化
- 缓存过期策略:
- 设置合理的缓存过期时间,对于不经常变化的数据,设置较长的过期时间;对于频繁变化的数据,设置较短的过期时间,以平衡缓存命中率和数据一致性。
- 缓存清理:
- 定期清理过期缓存,避免缓存占用过多内存。可以使用定时器或在应用启动/关闭时进行清理。
- 批量请求:
- 对于多个相关请求,可以合并为一个批量请求,减少HTTP请求次数,提高性能。例如,多个分页数据请求在满足一定条件下可以合并为一个请求获取多个分页的数据,然后再按分页粒度缓存。