高并发11-布隆过滤器

前言

- 黑客流量攻击:故意访问不存在的数据,导致程序不断访问DB数据库的数据(缓存击穿
- 黑客安全阻截:当黑客访问不存在的缓存时迅速返回避免缓存及DB挂掉
- 思考:如果让你实现这个功能你会怎么做? key:10000 10001 10002 10003 大集合,key是否在集合里面
- 温故而知新:分析java常用数据结构复习 set map key,value list 有序get[0]、get[1];
- list.contain (key)遍历数据,进行equals()比较,性能小
- set.contain(key) hashcode比较,性能较高,64位 1G
- map.get(key) hashcode比较,性能还行


- 概念:

- **布隆过滤器**(英语:Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的[二进制](https://zh.wikipedia.org/wiki/%E4%BA%8C%E8%BF%9B%E5%88%B6)向量和一系列随机[映射函数](https://zh.wikipedia.org/wiki/%E6%98%A0%E5%B0%84)。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
- 优点:

- 相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。布隆过滤器存储空间和插入/查询时间都是常数({\displaystyle O(k)}![O(k)](https://wikimedia.org/api/rest_v1/media/math/render/svg/f5ec39041121b14e8c2b1a986c9b04547b223e3c))。另外,散列函数相互之间没有关系,方便由硬件并行实现。布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势

 

 


- 缺点

- 但是布隆过滤器的缺点和优点一样明显。误算率是其中之一。随着存入的元素数量增加,误算率随之增加。但是如果元素数量太少,则使用散列表足矣

 

 

- 布隆过滤器的其他使用场景

  **网页爬虫对URL的去重,避免爬取相同的URL地址;**

  **反垃圾邮件,从数十亿个垃圾邮件列表中判断某邮箱是否垃圾邮箱(同理,垃圾短信);**

  **缓存击穿,将已存在的缓存放到布隆中,当黑客访问不存在的缓存时迅速返回避免缓存及DB挂掉。**

- 布隆过滤器实现原理图解

 

 

谷歌布隆过滤器实现会员转盘抽奖

- 需求分析步骤

  * 互联网功能需求分析
  * 这是一个抽奖程序,只针对会员用户有效
  * 抽离出功能所有api
  * 制定存储方案
  * 性能优化方案分析

 

 

- 成型互联网产品用户量上千万,日常百万,怎么做到高性能非会员过滤

- 这是一个布隆过滤器的经典使用场景

- 通过google布隆过滤器存储会员数据实战

  引入jar包

<dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>21.0</version>
        </dependency>

 

  * 程序启动时将数据放入内存中

package com.concurrent.service;

import com.concurrent.domain.SysUser;
import com.concurrent.domain.SysUserExample;
import com.concurrent.mapper.SysUserMapper;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;

@Service
public class BloomFilterService {

    @Resource
    private SysUserMapper sysUserMapper;

    private BloomFilter<Integer> bf;

    /***
     * PostConstruct 程序启动时候加载此方法
     */
    @PostConstruct
    public void initBloomFilter() {
        SysUserExample sysUserExample = new SysUserExample();
        List<SysUser> sysUserList = sysUserMapper.selectByExample(sysUserExample);
        if(CollectionUtils.isEmpty(sysUserList)){
            return;
        }
        //创建布隆过滤器(默认3%误差)
        bf = BloomFilter.create(Funnels.integerFunnel(),sysUserList.size());
        for (SysUser sysUser:sysUserList) {
            bf.put(sysUser.getId());
        }
    }

    /***
     * 判断id可能存在于布隆过滤器里面
     * @param id
     * @return
     */
    public boolean userIdExists(int id){
        return bf.mightContain(id);
    }

}

 


  * google自动创建布隆过滤器
  * 用户ID进来之后判断是否是会员

package com.concurrent.controller;


import com.concurrent.service.BloomFilterService;
import com.concurrent.util.RedisService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class BloomFilterController {

    @Resource
    private BloomFilterService bloomFilterService;

    @Resource
    private RedisService redisService;


    @RequestMapping("/bloom/idExists")
    public boolean ifExists(int id){
        return bloomFilterService.userIdExists(id);
    }



}

 

- 数据库

 


 CREATE TABLE `sys_user` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
    `user_name` varchar(11) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '用户名',
    `image` varchar(11) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '用户头像',
    PRIMARY KEY (`id`)
  ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

 

 goole布隆过滤器与Redis布隆过滤器

- google布隆过滤器的缺陷与思考

  - 基于内存布隆过滤器有什么特点

  - 内存级别产物
  - 重启即失效
  - 本地内存无法用在分布式场景
  - 不支持大数据量存储

- 需求分析步骤

  - 互联网功能需求分析
  - 这是一个抽奖程序,只针对会员用户有效
  - 抽离出功能所有api
  - 制定存储方案
  - 性能优化方案分析

- Redis布隆过滤器

  * 可扩展性Bloom过滤器
  * 一旦Bloom过滤器达到容量,就会在其上创建一个新的过滤器
  * 不存在重启即失效或者定时任务维护的成本
  * 基于goole实现的布隆过滤器需要启动之后初始化布隆过滤器
  * 缺点:
    * 需要网络IO,性能比基于内存的过滤器低

- 选择:

  优先基于数据量进行考虑

posted @ 2019-10-09 11:49  valar-dohaeris  阅读(439)  评论(0)    收藏  举报