1.什么是缓存穿透?
缓存穿透指的是,攻击者在访问数据时,使用一些不存在的KEY访问我们的应用,
后端应会先在redis中去查找,由于查找不到数据,就会去数据库中获取数据,这样攻击者就可以透过缓存访问数据库。
因此数据库的压力会太大而导致应用崩溃。因此我们可以采用布隆过滤器防止这个问题。
2. 布隆过滤器的原理
布隆过滤器是先初始化一个大的二进制数组。
我们预先将数据库的ID数据,查找出来,对这个数组进行初始化,我们可以将数据进行hash,对数组的进行标记。
比如 010101000000,如果一个不存在的数据,提取的数据对应的bit 值为0 ,那么表示数据不存在,具体可以看网上的教程。
当然也有可能出现误判的情况,比如提取到的位数全部唯一,这种情况几率会很小。
比如攻击者将一个不存在的数据传过来,那么布隆过滤器判断这个ID不存在。直接返回就好。
3.实现代码
3.1 使用redis
导入maven包。
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson-all</artifactId> <version>3.16.4</version> </dependency>
编写代码:
public static void main(String[] args) { Config config=new Config(); config.useSingleServer(). setAddress("redis://localhost:6379") .setPassword("redxun"); RedissonClient client= Redisson.create(config); RBloomFilter<String> filter=client.getBloomFilter("bloom"); filter.tryInit(1000000L,0.01); filter.add("1001"); filter.add("1002"); System.err.println(filter.contains("1001")); System.err.println(filter.contains("1004")); }
1.filter.add 这些代码应该在初始化布隆过滤器实现。
2.使用 filter.contains 是判断 指定的KEY是否存在。
3.2 使用guava
引入pom
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>23.0</version> </dependency>
java代码
public static void main(String[] args) { // 预期插入数量 long capacity = 10000L; // 错误比率 double errorRate = 0.01; // 创建布隆过滤器对象 BloomFilter bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), capacity,errorRate); // 向过滤器中添加元素 bloomFilter.put("element001"); bloomFilter.put("element003"); // 判断元素是否存在 System.out.println(bloomFilter.mightContain("element001"));//true System.out.println(bloomFilter.mightContain("element002"));//false // 已添加到Bloom过滤器的元素的数量 System.out.println(bloomFilter.approximateElementCount());// 2 // 返回元素存在的错误概率 System.out.println(bloomFilter.expectedFpp()); }