中山专业网站建设模板代理,优酷视频网站开发,标志设计图片大全简单,伪春菜wordpressRedis学习——高级篇⑥ Redis7高级之简单实现布隆过滤器BloomFilter #xff08;七#xff09; 7 布隆过滤器1. 是什么2.能干嘛3.实现原理和数据结构4.使用三步骤5.尝试手写简单的布隆过滤器#xff0c;结合bitmap1.整体架构2.步骤设计3 springboot redis mybatis布… Redis学习——高级篇⑥ Redis7高级之简单实现布隆过滤器BloomFilter 七 7 布隆过滤器1. 是什么2.能干嘛3.实现原理和数据结构4.使用三步骤5.尝试手写简单的布隆过滤器结合bitmap1.整体架构2.步骤设计3 springboot redis mybatis布隆过滤器 整合 6.布隆过滤器优缺点 Redis7高级之简单实现布隆过滤器BloomFilter 七
7 布隆过滤器 1. 是什么
由一个初值都为零的bit数组和多个哈希函数构成用来快速判断集合中是否存在某个元素
布隆过滤器的初始状态
目的
减少内存占用
方式
不保存数据信息只是在内存中做一个是否存在的标记flag
本质
判断具体数据是否村在于一个大的集合中
布隆过滤器是一种类似 set 的数据结构只是统计结果在巨量数据下有点小瑕疵不够完美
它实际上是一个很长的二进制数组(00000000)一系列随机hash算法映射函数主要用于判断一个元素是否在集合中。 通常我们会遇到很多要判断一个元素是否在某个集合中的业务场景一般想到的是将集合中所有元素保存起来然后通过比较确定。链表、树、哈希表等等数据结构都是这种思路。但是随着集合中元素的增加我们需要的存储空间也会呈现线性增长最终达到瓶颈。同时检索速度也越来越慢上述三种结构的检索时间复杂度分别为 O ( n ) O(n) O(n), O ( l o g n ) O(logn) O(logn), O ( 1 ) O(1) O(1)。这个时候布隆过滤器Bloom Filter就应运而生 2.能干嘛
高效地插入和查询占用空间少返回地结果是不确定性 不完美性
一个元素如果判断结果存在时元素不一定存在不存在时元素一定不存在
布隆过滤器可以添加元素但是不能删除元素
涉及到hashcode判断依据删掉元素会导致误判率增加为什么不能删掉 因为他是有多个 hash 函数对一个值进行多次 hash 运算将获得的每个值在对应位置存 1 容易导致这个 1 也代表别的值一旦删除另一个值也无法通过 3.实现原理和数据结构
布隆过滤器(Bloom Filter) 是一种专门用来解决去重问题的高级数据结构。
实质就是一个大型位数组和几个不同的无偏hash函数无偏表示分布均匀。由一个初值为零地bit数组和多个哈希函数构成用来快速判断某个数据是否存在。但是跟HyperLogLog一样他也有一点不精确存在一定的误判概率 添加 key 时 使用多个 hash 函数对key进行hash运算得到一个整数索引值对位数组长度进行取模运算得到一个位置每个 hash 函数都会得到一个不同的位置将这几个位置都置 1 就完成了 add 操作 查询 key 时 只要有其中一位是零就表示这个key不存在但如果都是1则不一定存在对应的key 结论 有可能有无肯定无 hash 冲突导致数据不精准1 查询的时候看看这几个点是不是 1 就可以大概率直到集合中有没有它了如果这些点有任何一个为零则被查询变量一定不在如果都是 1则被查询变量很可能存在正是基于布隆过滤器的快速检测特性我们可以在把数据写入数据库时使用布隆过滤器做个标记当缓存缺失后应用查询数据库时可以通过查询布隆过滤器快速判断数据是否存在如果不存在就不用再去数据库中查询了。这样一来即使发生了缓存穿透了大量请求只会查询Redis和布隆过滤器而不会积压到数据库也就不会影响数据库的正常运行。布隆过滤器可以使用redis实现本身就能承担较大的并发访问压力 hash 冲突导致数据不精准2 哈希函数的概念是将任意大小的输入数据转换成特定大小的输出数据的函数转换后的数据称为哈希值或哈希编码也叫散列值 如果两个散列值是不相同的根据同一函数那么这两个散列值的原始输入也是不相同的。 这个特性是散列函数具有确定性的结果具有这种性质的散列函数称为单向散列函数。 散列函数的输入和输出不是唯一对应关系的如果两个散列值相同两个输入值很可能是相同的但也可能不同这种情况称为“散列碰撞collision” 用 hash表存储大数据量时空间效率还是很低当只有一个 hash 函数时还很容易发生哈希碰撞。 4.使用三步骤
本质上 是由长度为 m 的位向量或位列表仅包含 0 或 1 位值的列表组成最初所有的值均设置为 0 添加数据为了尽量地址不冲突使用多个hash函数对key进行运算算得一个下标索引值然后对数据长度进行取模运算得到一个位置每个 hash 函数都会算得一个不同的位置。再把位数组的这几个位置都置为 1 就完成了 add 操作。
对字符串进行多次hash(key) → 取模运行→ 得到坑位 向布隆过滤器查询某个key是否存在时先把这个 key 通过相同的多个 hash 函数进行运算查看对应的位置是否都为 1只要有一个位为零那么说明布隆过滤器中这个 key 不存在如果这几个位置全都是 1那么说明极有可能存在
总结 是否存在 有可能有无肯定无 使用是最好不要让实际元素数量远大于初始化数量一次给够避免扩容当实际元素数量超过初始化数量应该对布隆过滤器进行重建重新分配一个size 更大的过滤器再将所有的历史元素批量add 5.尝试手写简单的布隆过滤器结合bitmap
1.整体架构 缓存穿透是什么 一般情况下先查询缓存redis是否有该条数据缓存中没有时再查询数据库。 当数据库也不存在该条数据时每次查询都要访问数据库这就是缓存穿透。 缓存透带来的问题是当有大量请求查询数据库不存在的数据时就会给数据库带来压力甚至会拖垮数据库。 可以使用布隆过滤器解决缓存穿透的问题; 把已存在数据的key存在布隆过滤器中相当于redis前面挡着一个布隆过滤器。 当有新的请求时先到布隆过滤器中查询是否存在: 如果布隆过滤器中不存在该条数据则直接返回; 如果布隆过滤器中已存在才去查询缓存redis,如果redis里没查询到则再查询Mysq|数据库 2.步骤设计
setBit的构建过程 PostConstruct 初始化白名单数据计算元素hash值得到hash值算出对应的二进制数组的坑位将对应坑位的值修改为数字1表示存在 getBit查询是否存在 计算元素hash值得到hash值算出对应的二进制数组的坑位返回对应坑位的值0表示无1表示存在
3 springboot redis mybatis布隆过滤器 整合 使用Mapper4自动生成 先创建 mybatis-generator 工程
建表sql
CREATE TABLE t_customer (id int(20) NOT NULL AUTO_INCREMENT,cname varchar(50) NOT NULL,age int(10) NOT NULL,phone varchar(20) NOT NULL,sex tinyint(4) NOT NULL,birth timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (id),KEY idx_cname (cname)) ENGINEInnoDB AUTO_INCREMENT10 DEFAULT CHARSETutf8mb4pom
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.xfcy/groupIdartifactIdmybatis_generator/artifactIdversion1.0-SNAPSHOT/versionparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.6.10/versionrelativePath//parentproperties!-- 依赖版本号 --project.build.sourceEncodingUTF-8/project.build.sourceEncodingmaven.compiler.source1.8/maven.compiler.sourcemaven.compiler.target1.8/maven.compiler.targetjava.version1.8/java.versionhutool.version5.5.8/hutool.versiondruid.version1.1.18/druid.versionmapper.version4.1.5/mapper.versionpagehelper.version5.1.4/pagehelper.versionmysql.version5.1.39/mysql.versionswagger2.version2.9.2/swagger2.versionswagger-ui.version2.9.2/swagger-ui.versionmybatis.spring.version2.1.3/mybatis.spring.version/propertiesdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!--Mybatis 通用mapper tk单独使用自己带着版本号--dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.4.6/version/dependency!--mybatis-spring--dependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion${mybatis.spring.version}/version/dependency!-- Mybatis Generator --dependencygroupIdorg.mybatis.generator/groupIdartifactIdmybatis-generator-core/artifactIdversion1.4.0/versionscopecompile/scopeoptionaltrue/optional/dependency!--通用Mapper--dependencygroupIdtk.mybatis/groupIdartifactIdmapper/artifactIdversion${mapper.version}/version/dependency!--persistence--dependencygroupIdjavax.persistence/groupIdartifactIdpersistence-api/artifactIdversion1.0.2/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scopeexclusionsexclusiongroupIdorg.junit.vintage/groupIdartifactIdjunit-vintage-engine/artifactId/exclusion/exclusions/dependency/dependenciesbuildresourcesresourcedirectory${basedir}/src/main/java/directoryincludesinclude**/*.xml/include/includes/resourceresourcedirectory${basedir}/src/main/resources/directory/resource/resourcespluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfigurationexcludesexcludegroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/exclude/excludes/configuration/pluginplugingroupIdorg.mybatis.generator/groupIdartifactIdmybatis-generator-maven-plugin/artifactIdversion1.3.6/versionconfigurationconfigurationFile${basedir}/src/main/resources/generatorConfig.xml/configurationFileoverwritetrue/overwriteverbosetrue/verbose/configurationdependenciesdependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion${mysql.version}/version/dependencydependencygroupIdtk.mybatis/groupIdartifactIdmapper/artifactIdversion${mapper.version}/version/dependency/dependencies/plugin/plugins/build
/projectsrc/main/resources
新建 config.properties
#t_customer表包名
#com.xfcy 输自己用的包名 要不然不能直接cv到自己用的工程里
package.namecom.xfcyjdbc.driverClass com.mysql.jdbc.Driver
jdbc.url jdbc:mysql://localhost:3306/db_boot
jdbc.user root
jdbc.password 123456新建 generatorConfig.xml
?xml version1.0 encodingUTF-8?
!DOCTYPE generatorConfigurationPUBLIC -//mybatis.org//DTD MyBatis Generator Configuration 1.0//ENhttp://mybatis.org/dtd/mybatis-generator-config_1_0.dtdgeneratorConfigurationproperties resourceconfig.properties/context idMysql targetRuntimeMyBatis3Simple defaultModelTypeflatproperty namebeginningDelimiter value/property nameendingDelimiter value/plugin typetk.mybatis.mapper.generator.MapperPluginproperty namemappers valuetk.mybatis.mapper.common.Mapper/property namecaseSensitive valuetrue//pluginjdbcConnection driverClass${jdbc.driverClass}connectionURL${jdbc.url}userId${jdbc.user}password${jdbc.password}/jdbcConnectionjavaModelGenerator targetPackage${package.name}.entities targetProjectsrc/main/java/sqlMapGenerator targetPackage${package.name}.mapper targetProjectsrc/main/java/javaClientGenerator targetPackage${package.name}.mapper targetProjectsrc/main/java typeXMLMAPPER/!-- 输入表名 t_customer --table tableNamet_customer domainObjectNameCustomergeneratedKey columnid sqlStatementJDBC//table/context
/generatorConfiguration一键生成
ps生成这两个即可 整合redis 新建工程
POM parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.6.10/versionrelativePath//parentpropertiesproject.build.sourceEncodingUTF-8/project.build.sourceEncodingmaven.compiler.source1.8/maven.compiler.sourcemaven.compiler.target1.8/maven.compiler.targetjunit.version4.12/junit.versionlog4j.version1.2.17/log4j.versionlombok.version1.16.18/lombok.version/propertiesdependencies!--SpringBoot通用依赖模块--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!--jedis--dependencygroupIdredis.clients/groupIdartifactIdjedis/artifactIdversion4.3.1/version/dependency!--lettuce--!--dependencygroupIdio.lettuce/groupIdartifactIdlettuce-core/artifactIdversion6.2.1.RELEASE/version/dependency--!--SpringBoot与Redis整合依赖--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependencydependencygroupIdorg.apache.commons/groupIdartifactIdcommons-pool2/artifactId/dependency!--swagger2--dependencygroupIdio.springfox/groupIdartifactIdspringfox-swagger2/artifactIdversion2.9.2/version/dependencydependencygroupIdio.springfox/groupIdartifactIdspringfox-swagger-ui/artifactIdversion2.9.2/version/dependency!--Mysql数据库驱动--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.47/version/dependency!--SpringBoot集成druid连接池--dependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactIdversion1.1.10/version/dependencydependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.1.16/version/dependency!--mybatis和springboot整合--dependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion1.3.0/version/dependency!--hutool--dependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactIdversion5.2.3/version/dependency!--persistence--dependencygroupIdjavax.persistence/groupIdartifactIdpersistence-api/artifactIdversion1.0.2/version/dependency!--通用Mapper--dependencygroupIdtk.mybatis/groupIdartifactIdmapper/artifactIdversion4.1.5/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-autoconfigure/artifactId/dependency!--通用基础配置junit/devtools/test/log4j/lombok/--dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion${junit.version}/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependencydependencygroupIdlog4j/groupIdartifactIdlog4j/artifactIdversion${log4j.version}/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion${lombok.version}/versionoptionaltrue/optional/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/buildYML
server.port7070# swagger
spring.swagger2.enabledtrue
#在springboot2.6.X结合swagger2.9.X会提示documentationPluginsBootstrapper空指针异常
#原因是在springboot2.6.X中将SpringMVC默认路径匹配策略从AntPathMatcher更改为PathPatternParser
# 导致出错解决办法是matching-strategy切换回之前ant_path_matcher
spring.mvc.pathmatch.matching-strategyant_path_matcher# redis单机
spring.redis.database0
## 修改为自己真实IP
spring.redis.host192.168.238.111
spring.redis.port6379
spring.redis.password123456
spring.redis.lettuce.pool.max-active8
spring.redis.lettuce.pool.max-wait-1ms
spring.redis.lettuce.pool.max-idle8
spring.redis.lettuce.pool.min-idle0# logging
logging.level.rootinfo
logging.level.com.atguigu.redis7info
logging.pattern.console%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n logging.file.nameD:/mylogs2023/redis7_study.log
logging.pattern.file%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n# alibaba.druid
spring.datasource.typecom.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-namecom.mysql.jdbc.Driver
spring.datasource.urljdbc:mysql://localhost:3306/db_boot?useUnicodetruecharacterEncodingutf-8useSSLfalse
spring.datasource.usernameroot
spring.datasource.password123456
spring.datasource.druid.test-while-idlefalse# mybatis
mybatis.mapper-locationsclasspath:mapper/*.xml
mybatis.type-aliases-packagecom.xfcy.entities启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;/*** customer 是有关简单手写布隆过滤器*/
MapperScan(com.xfcy.mapper) // import tk.mybatis.spring.annotation.MapperScan;
SpringBootApplication
public class Redis7Study2Application {public static void main(String[] args) {SpringApplication.run(Redis7Study2Application.class, args);}
}布隆过滤器
filter 包 BloomFilterInit
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.Resource;/*** 布隆过滤器白名单初始化工具类一开始就设置一部分数据为白名单所有* 白名单业务默认规定布隆过滤器有redis 有可能有 布隆过滤器无 redis一定无* 白名单业务默认规定whitelistCustomer*/
Component
Slf4j
public class BloomFilterInit {Resourceprivate RedisTemplate redisTemplate;PostConstruct // 初始化白名单数据public void init() {// 1.白名单客户加载到布隆过滤器String key customer:11;// 2.计算hashValue由于存在计算出来负数的可能取绝对值int hashValue Math.abs(key.hashCode());// 3.通过hashValue 和 2的32次方后取余获得对应的下标坑位long index (long) (hashValue % Math.pow(2, 32));log.info(key 对应的坑位 index {}, index);// 4.设置redis里面的bitmap对应类型的坑位将该值设置为1redisTemplate.opsForValue().setBit(whitelistCustomer, index, true);}
}utils包 CheckUtils
import javax.annotation.Resource;Component
Slf4j
public class CheckUtils {Resourceprivate RedisTemplate redisTemplate;public boolean checkWithBloomFilter(String checkItem, String key){int hashValue Math.abs(key.hashCode());long index (long) (hashValue % Math.pow(2, 32));boolean existOK redisTemplate.opsForValue().getBit(checkItem, index);log.info(----: key 对应坑位下标index index 是否存在 existOK);return existOK;}
}业务类 entity 拷贝生成的 Customer类 mapper 拷贝生成的CustomerMapper 类 src/main/resources/mapper 拷贝生成的 CustomerMapper.xml service类 (个人修改了一部分 加上了双检加锁)
import com.xfcy.entities.Customer;
import com.xfcy.mapper.CustomerMapper;
import com.xfcy.utils.CheckUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;Service
Slf4j
public class CustomerService {public static final String CACHE_KEY_CUSTOMER customer:;Resourceprivate CustomerMapper customerMapper;Resourceprivate RedisTemplate redisTemplate;Resourceprivate CheckUtils checkUtils;/*** 写操作** param customer*/public void addCustomer(Customer customer) {int i customerMapper.insertSelective(customer);if (i 0) {// mysql 插入成功需要重新查询一次将数据写进redisCustomer result customerMapper.selectByPrimaryKey(customer.getId());// redis缓存keyString key CACHE_KEY_CUSTOMER customer.getId();// 写入redisredisTemplate.opsForValue().set(key, result);}}/*** 读操作 双检加锁 null缓存*/public Customer findCustomerById(Integer customerId) {Customer customer null;// 缓存redis的key名称String key CACHE_KEY_CUSTOMER customerId;// 1.去redis上查询customer (Customer) redisTemplate.opsForValue().get(key);// 2. 如果redis有直接返回 如果redis没有在mysql上查询if (customer null) {// 3.对于高QPS的优化进来就先加锁保证一个请求操作让外面的redis等待一下避免击穿mysql大公司的操作 synchronized (CustomerService.class) {// 3.1 第二次查询redis加锁后customer (Customer) redisTemplate.opsForValue().get(key);// 4.mysql有redis无if (customer null) {// 5.再去查询我们的mysqlcustomer customerMapper.selectByPrimaryKey(customerId);if (customer null) {// 6.1 defaultNull 规定为redis查询为空、MySQL查询也没有缓存一个defaultNull标识为空以防缓存穿透redisTemplate.opsForValue().set(key, defaultNull, 7L, TimeUnit.DAYS);} else {// 6.2 把mysql查询到的数据会写到到redis 保持双写一致性 7天过期redisTemplate.opsForValue().set(key, customer, 7L, TimeUnit.DAYS);}}}}return customer;}/*** 业务逻辑没有写错对于QPS 1000 可以使用* param customerId* return*/
// public Customer findeCustomerById(Integer customerId) {
// Customer customer null;
// // 缓存redis的key名称
// String key CACHE_KEY_CUSTOMER customerId;
// // 1.去redis上查询
// customer (Customer) redisTemplate.opsForValue().get(key);
// // 2. 如果redis有直接返回 如果redis没有在mysql上查询
// if(customer null) {
// customer customerMapper.selectByPrimaryKey(customerId);
// if (customer null) {
// redisTemplate.opsForValue().set(key, customer);
// }
// }
// return customer;
// }/*** 布隆过滤器 双检加锁 注意单个服务在分布式系统锁将锁不住** param customerId* return*/public Customer findCustomerByIdWithBloomFilter(Integer customerId) {Customer customer null;// 1.缓存redis的key名称String key CACHE_KEY_CUSTOMER customerId;if (!checkUtils.checkWithBloomFilter(whitelistCustomer, key)) {log.info(白名单没有此信息不可以访问 key);return null;}// 1.1 去redis上查询customer (Customer) redisTemplate.opsForValue().get(key);// 2. 如果redis有直接返回 如果redis没有在mysql上查询if (customer null) {// 3.对于高QPS的优化进来就先加锁保证一个请求操作让外面的redis等待一下避免击穿mysql大公司的操作 synchronized (CustomerService.class) {// 3.1 第二次查询redis加锁后customer (Customer) redisTemplate.opsForValue().get(key);// 4.mysql有redis无if (customer null) {// 5.再去查询我们的mysqlcustomer customerMapper.selectByPrimaryKey(customerId);if (customer null) {// 6.1 defaultNull 规定为redis查询为空、MySQL查询也没有缓存一个defaultNull标识为空以防缓存穿透redisTemplate.opsForValue().set(key, defaultNull, 7L, TimeUnit.DAYS);} else {// 6.2 把mysql查询到的数据会写到到redis 保持双写一致性 7天过期redisTemplate.opsForValue().set(key, customer, 7L, TimeUnit.DAYS);}}}}return customer;}
}controller
import com.xfcy.entities.Customer;
import com.xfcy.service.CustomerService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.sql.Date;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Random;Api(客户Customer接口布隆过滤器讲解)
RestController
Slf4j
public class CustomerController {Resourceprivate CustomerService customerService;ApiOperation(数据库初始化2条customer记录插入)RequestMapping(value /customer/add, method RequestMethod.POST)public void addCustomer() {for (int i 0; i 2; i) {Customer customer new Customer();customer.setCname(customer i);customer.setAge(new Random().nextInt(30)1);customer.setPhone(12345678910);customer.setSex((byte) new Random().nextInt(2));customer.setBirth(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));customerService.addCustomer(customer);}}ApiOperation(单个customer查询操作按照customerId查询)RequestMapping(value /customer/{customerId}, method RequestMethod.GET)public Customer findCustomerById(PathVariable(customerId) Integer customerId){return customerService.findCustomerById(customerId);}ApiOperation(布隆过滤器单个customer查询操作按照customerId查询)RequestMapping(value /bloomfilter/{customerId}, method RequestMethod.GET)public Customer findCustomerByIdWithBloomFilter(PathVariable(customerId) Integer customerId){return customerService.findCustomerByIdWithBloomFilter(customerId);}
}启动 swagger测试注意要看控制台
6.布隆过滤器优缺点
优点
高效地插入和查询内存占用 bit 空间少
缺点
不能删除元素 因为删除元素会导致误判率增加因为hash冲突同一个位置可能存的东西是多个共有的你删除一个元素的同时可能也把其他的删除了 存在误判不能精准过滤 有可能有无绝对无
为了解决布隆过滤器不能删除元素的问题布谷鸟过滤器横空出世。