面试题答案
一键面试实现思路
- 数据源更新触发:当广告投放数据在数据源(如数据库)发生更新时,通过数据库的事务机制、触发器或消息队列来捕获这个更新事件。例如,在关系型数据库中可以使用触发器,当特定表的数据更新时,向消息队列发送一条包含更新数据相关信息(如更新的记录ID、数据变更内容等)的消息。
- 缓存更新策略:
- 本地缓存:收到更新消息后,先更新本地缓存。可以采用写后失效策略,即当数据源更新后,直接使本地缓存中对应的缓存项失效。下次访问该数据时,本地缓存未命中,再从数据源重新读取并更新本地缓存。
- 分布式缓存:同样采用失效策略。利用分布式缓存(如Redis)的发布/订阅功能,当数据源更新时,发布一个主题消息通知所有相关的分布式缓存节点使对应缓存项失效。也可以采用主动更新策略,即直接向分布式缓存发送更新命令,更新缓存数据。但这种方式在高并发场景下可能会有一致性问题,所以失效策略更为常用。
- 顺序处理:为确保缓存更新的顺序性,避免出现脏数据,对于消息队列中的更新消息,按照一定的顺序(如基于数据ID排序)进行处理。可以使用单线程消费消息队列,或者在多线程消费时利用锁机制保证同一数据的更新顺序。
可能遇到的问题及解决方案
- 缓存穿透:
- 问题描述:查询一个不存在的数据,由于缓存中没有,每次都会查询数据源,给数据源带来压力。
- 解决方案:在缓存中设置一个空值(如空字符串或特定的占位符)并设置较短的过期时间,下次查询同样不存在的数据时,缓存命中,直接返回空值,避免查询数据源。也可以使用布隆过滤器,在查询前先判断数据是否可能存在,减少无效查询。
- 缓存雪崩:
- 问题描述:大量缓存项在同一时间过期,导致大量请求直接查询数据源,可能压垮数据源。
- 解决方案:为缓存设置随机过期时间,避免大量缓存同时过期。同时,可以采用二级缓存,当一级缓存失效时,从二级缓存获取数据,减轻数据源压力。另外,使用熔断机制,当数据源压力过大时,暂时拒绝部分请求,返回友好提示。
- 缓存击穿:
- 问题描述:一个热点数据的缓存过期瞬间,大量请求同时查询该数据,直接查询数据源,可能导致数据源压力过大。
- 解决方案:在缓存失效时,使用互斥锁(如分布式锁)保证只有一个请求能查询数据源并更新缓存,其他请求等待,待缓存更新后,再从缓存获取数据。也可以采用热点数据不过期的策略,通过后台线程定时更新缓存,避免缓存过期瞬间的高并发请求。