如何保证查询节目时避免缓存穿透?

举报
幼儿园老大* 发表于 2024/11/27 15:32:35 2024/11/27
【摘要】 阅读过上面章节的小伙伴应该知道了 缓存穿透是指查询的数据在缓存和数据库中都不存在,导致每次查询这条数据都会穿透过缓存,直接去查询数据库,相当于没有缓存一样。而这种问题在查询节目详情时同样会存在,比如说某个黑客调用节目详情接口时,就会传入一个不存在的节目id,先查一遍缓存,缓存不存在则再去查询数据库,结果数据库也不存在,当并发高时,就会对数据库造成很大的压力在注册用户功能中,我们结合了验证码和...

阅读过上面章节的小伙伴应该知道了 缓存穿透是指查询的数据在缓存和数据库中都不存在导致每次查询这条数据都会穿透过缓存,直接去查询数据库,相当于没有缓存一样。


而这种问题在查询节目详情时同样会存在,比如说某个黑客调用节目详情接口时,就会传入一个不存在的节目id,先查一遍缓存,缓存不存在则再去查询数据库,结果数据库也不存在,当并发高时,就会对数据库造成很大的压力


在注册用户功能中,我们结合了验证码和布隆过滤器的方案来解决缓存穿透,那么在查询节目详情功能中,应该用什么方案呢?我们从业务特点来入手:


正常用户查询节目详情时,都是事先查询了节目主页或者节目列表后,再来查询节目详情的,也就是说节目id时肯定存在缓存或者数据库中的,如果是缓存和数据库都不存在的节目id说明此id就是不正常的,服务收到了此id就应该直接拒绝,不再执行后续的流程

注意这里的关键点,如果判断节目id不存在,则说明此节目id肯定是不正常的,这是不是和布隆过滤器的判断特点非常的贴合!布隆过滤器的特点就是如果判断某个元素不存在,那么说明此元素一定就不存在!关于布隆过滤器的详细讲解,小伙伴可跳转下面章节进行学习、

配置

bloom-filter:
  name: program-detail-bloom-filter
  expectedInsertions: 1000
  falseProbability: 0.01

控制层

@ApiOperation(value = "查询详情(根据id)")
@PostMapping(value = "/detail")
public ApiResponse<ProgramVo> getDetail(@Valid @RequestBody ProgramGetDto programGetDto) {
    return ApiResponse.ok(programService.detail(programGetDto));
}
public ProgramVo detail(ProgramGetDto programGetDto) {
    //查询节目id是否存在布隆过滤器中
    compositeContainer.execute(CompositeCheckType.PROGRAM_DETAIL_CHECK.getValue(),programGetDto);
    //验证通过执行节目查询
    return getDetail(programGetDto);
}

验证的具体逻辑

@Component
public class ProgramBloomFilterCheckHandler extends AbstractComposite<ProgramGetDto> {
    
    @Autowired
    private BloomFilterHandler bloomFilterHandler;
    
    @Override
    protected void execute(final ProgramGetDto param) {
        boolean contains = bloomFilterHandler.contains(String.valueOf(param.getId()));
        if (!contains) {
            throw new DaMaiFrameException(BaseCode.PROGRAM_NOT_EXIST);
        }
    }
    
    @Override
    public String type() {
        return CompositeCheckType.PROGRAM_DETAIL_CHECK.getValue();
    }
    
    @Override
    public Integer executeParentOrder() {
        return 0;
    }
    
    @Override
    public Integer executeTier() {
        return 1;
    }
    
    @Override
    public Integer executeOrder() {
        return 1;
    }
}

可以看到这里是直接通过布隆过滤器来判断节目id是否存在的,但什么时候放进去的呢?

其实这里是在节目启动初始化的时候放入的,从数据库中查询出所有节目id然后放入布隆过滤器中,这么做也是为了方便小伙伴学习,节目启动后可以直接的来学习了。

而实际的生产环境肯定不会这么做,节目的数据上千万上亿,直接全部查询不现实,肯定是通过运营人员,添加好节目后,再添加到布隆过滤器中的,而这里的初始化流程同样值得小伙伴好好的学习,这里针对Spring的初始化不同策略进行封装成了组件,使用了抽象思想和设计模式,

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。