一文解决Redis中的缓存击穿问题(因为坑我都踩完了) 直接放DEMO
如果对您有帮助或者解决了您的问题, 就帮我点个赞或者评论关注支持吧, 您的鼓励是我写博客的最大支持, 感谢!
布隆过滤器:
一种来检索元素是否在给定大集合中的数据结构,这种数据结构是高效且性能很好的,但缺点是具有一定的错误识别率和删除难度。并且,理论情况下,添加到集合中的元素越多,误报的可能性就越大
二进制位数组和一系列随机哈希函数两部分组成的数据结构
位数组中的每个元素都只占用 1 bit ,并且每个元素只能是 0 或者 1。这样申请一个 100w 个元素的位数组只占用 1000000 / 8 = 125000 B = 15625 byte ≈ 15.3kb 的空间
布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在
一 原理
当一个元素加入布隆过滤器中的时候,会进行如下操作:
- 使用布隆过滤器中的哈希函数对元素值进行计算,得到哈希值(有几个哈希函数得到几个哈希值)。
- 根据得到的哈希值,在位数组中把对应下标的值置为 1。
当我们需要判断一个元素是否存在于布隆过滤器的时候,会进行如下操作:
- 对给定元素再次进行相同的哈希计算;
- 得到值之后判断位数组中的每个元素是否都为 1,如果值都为 1,那么说明这个值在布隆过滤器中,如果存在一个值不为 1,说明该元素不在布隆过滤器中。
二 动手DEMO
package redis;
import java.util.BitSet;
public class MyBloomFilter {
// 位数组大小
private static final int DEFAULT_SIZE = 2 << 24;
// 位数组
private BitSet bitSet = new BitSet(DEFAULT_SIZE);
// 传入不同的seed创建 6 个不同的哈希函数
private static final int[] SEEDS = new int[] { 3, 13, 46, 71, 91, 134 };
private SimpleHash[] func = new SimpleHash[SEEDS.length];
// 静态内部类, 用于hash操作
public static class SimpleHash {
private int cap;
private int seed;
public SimpleHash(int cap, int seed) {
super();
this.cap = cap;
this.seed = seed;
}
public int hash(Object value) {
int h;
return (value == null) ?
0 : Math.abs(seed * (cap - 1)
& ((h = value.hashCode())
^ (h >>> 16)));
}
}
public MyBloomFilter() {
super();
for (int i = 0; i < SEEDS.length; i++) {
func[i] = new SimpleHash(DEFAULT_SIZE, SEEDS[i]);
}
}
public void add(Object vaObject) {
for (SimpleHash sf : func) {
bitSet.set(sf.hash(vaObject), true);
}
}
public boolean contains(Object vaObject) {
boolean ret = true;
for (SimpleHash f : func) {
ret = ret && bitSet.get(f.hash(vaObject));
}
return ret;
}
}
如果对您有帮助或者解决了您的问题, 就帮我点个赞或者评论关注支持吧, 您的鼓励是我写博客的最大支持, 感谢!
三 在Redis中使用
直接用docker
➜ ~ docker run -p 6379:6379 --name redis-redisbloom redislabs/rebloom:latest
➜ ~ docker exec -it redis-redisbloom bash
root@21396d02c252:/data# redis-cli
127.0.0.1:6379>
测试
127.0.0.1:6379> BF.ADD myFilter java
(integer) 1
127.0.0.1:6379> BF.ADD myFilter javaguide
(integer) 1
127.0.0.1:6379> BF.EXISTS myFilter java
(integer) 1
127.0.0.1:6379> BF.EXISTS myFilter javaguide
(integer) 1
127.0.0.1:6379> BF.EXISTS myFilter github
(integer) 0