/**
* 缓存击穿
* @author
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:config/spring/spring-dao.xml",
"classpath:config/spring/spring-bean.xml",
"classpath:config/spring/spring-redis.xml"})
public class CacheBreakDownTest {
private static final Logger logger = LoggerFactory.getLogger(CacheBreakDownTest.class); private static final int THREAD_NUM = 100;//线程数量 @Resource
private UserDao UserDao; @Resource
private RedisTemplate redisTemplate; private int count = 0; //初始化一个计数器
private CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUM); private BloomFilter<String> bf; List<UserDto> allUsers; @PostConstruct
public void init(){
//将数据从数据库导入到本地
allUsers = UserDao.getAllUser();
if(allUsers == null || allUsers.size()==0){
return;
}
//创建布隆过滤器(默认3%误差)
bf = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), allUsers.size());
//将数据存入布隆过滤器
for(UserDto userDto : allUsers){
bf.put(userDto.getUserName());
}
} @Test
public void cacheBreakDownTest(){
for(int i=0;i<THREAD_NUM;i++){
new Thread(new MyThread()).start();
//计数器减一
countDownLatch.countDown();
}
try {
Thread.currentThread().join();
} catch (InterruptedException e) {
e.printStackTrace();
}
} class MyThread implements Runnable{ @Override
public void run() {
try {
//所有子线程等待,当子线程全部创建完成再一起并发执行后面的代码
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
//随机产生一个字符串
String randomUser = UUID.randomUUID().toString();
// String randomUser = allUsers.get(new Random().nextInt(allUsers.size())).getUserName();
String key = "Key:"+randomUser; //如果布隆过滤器中不存在这个用户直接返回,将流量挡掉
if(!bf.mightContain(randomUser)){
System.out.println("bloom filter don't has this user");
return;
}
//查询缓存,如果缓存中存在直接返回缓存数据
ValueOperations<String,String> operation = (ValueOperations<String, String>) redisTemplate.opsForValue();
synchronized (countDownLatch) {
Object cacheUser = operation.get(key);
if(cacheUser!=null){
System.out.println("return user from redis");
return;
}
//如果缓存不存在查询数据库
List<UserDto> user = UserDao.getUserByUserName(randomUser);
if(user == null || user.size() == 0){
return;
}
//将mysql数据库查询到的数据写入到redis中
System.out.println("write to redis");
operation.set("Key:"+user.get(0).getUserName(), user.get(0).getUserName());
}
} }
}

  demo2

@RunWith(SpringRunner.class)
@SpringBootTest
public class BloomFilterTest {
private BloomFilter<Integer> bloomFilter; private int size = 1000000;
@Before
public void init(){
//不设置第三个参数时,误判率默认为0.03
//bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size);
//进行误判率的设置,自动计算需要几个hash函数。bit数组的长度与size和fpp参数有关
//过滤器内部会对size进行处理,保证size为2的n次幂。
bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, 0.01);
for(int i = 0; i < size; i++){
bloomFilter.put(i);
}
}
@Test
public void testBloomFilter(){
for(int i = 0; i < size; i++){
if(!bloomFilter.mightContain(i)){
//不会打印,因为不存在的情况不会出现误判
System.out.println("不存在的误判" + i);
}
} List<Integer> list = new ArrayList<>(1000);
for (int i = size + 10000; i < size + 20000; i++) {
if (bloomFilter.mightContain(i)) {
list.add(i);
}
}
//根据设置的误判率
System.out.println("存在的误判数量:" + list.size());
}
}

  布隆过滤器有以下应用场景:

  1、黑名单,比如邮件黑名单过滤器,判端邮件地址是否在黑名单中。

  2、网络爬虫,判端url是否已经被爬取过。

  3、首次访问,判端访问网站的IP是否是第一次访问。

  4、缓存击穿,防止非法攻击,频繁发送无法命中缓存的请求,导致缓存击穿,最总引起缓存雪崩。

  5、检查英文单词是否拼写正确。

  6、K-V系统快速判断某个key是否存在,典型的例子有Hbase,Hbase的每个Region中都包含一个BloomFilter,用于在查询时快速判断某个key在该region中是否存在,如果不存在,直接返回,节省掉后续的查询。

  扩展,如何让布隆过滤器支持删除。

  进行计数删除,但是计数删除需要存储一个数值,而不是原先的 bit 位,会增大占用的内存大小。这样的话,增加一个值就是将对应索引槽上存储的值加一,删除则是减一,判断是否存在则是看值是否大于0。

布隆过滤器的demo的更多相关文章

  1. 浅析布隆过滤器及实现demo

    布隆过滤器 布隆过滤器(Bloom Filter)是一种概率空间高效的数据结构.它与hashmap非常相似,用于检索一个元素是否在一个集合中.它在检索元素是否存在时,能很好地取舍空间使用率与误报比例. ...

  2. 【布隆过滤器】基于Hutool库实现的布隆过滤器Demo

    布隆过滤器出现的背景: 如果想判断一个元素是不是在一个集合里,一般想到的是将集合中所有元素保存起来,然后通过比较确定.链表.树.散列表(又叫哈希表,Hash table)等等数据结构都是这种思路,存储 ...

  3. 布隆过滤器(BloomFilter)持久化

    摘要 Bloomfilter运行在一台机器的内存上,不方便持久化(机器down掉就什么都没啦),也不方便分布式程序的统一去重.我们可以将数据进行持久化,这样就克服了down机的问题,常见的持久化方法包 ...

  4. 【面试突击】-缓存击穿(布隆过滤器 Bloom Filter)

    原文地址:https://blog.csdn.net/fouy_yun/article/details/81075432 前面的文章介绍了缓存的分类和使用的场景.通常情况下,缓存是加速系统响应的一种途 ...

  5. python实现布隆过滤器及原理解析

    python实现布隆过滤器及原理解析     布隆过滤器( BloomFilter )是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地 ...

  6. 细谈布隆过滤器及Redis实现

    ​ 何为布隆过滤器? 本质上是一种数据结构,是1970年由布隆提出的.它实际上是一个很长的二进制向量(位图)和一系列随机映射函数(哈希函数).可以用于检索一个元素是否在一个集合中. 数据结构: 布隆过 ...

  7. 布隆过滤器的概述及Python实现

    布隆过滤器 布隆过滤器是一种概率空间高效的数据结构.它与hashmap非常相似,用于检索一个元素是否在一个集合中.它在检索元素是否存在时,能很好地取舍空间使用率与误报比例.正是由于这个特性,它被称作概 ...

  8. 【转】Bloom Filter布隆过滤器的概念和原理

    转自:http://blog.csdn.net/jiaomeng/article/details/1495500 之前看数学之美丽,里面有提到布隆过滤器的过滤垃圾邮件,感觉到何其的牛,竟然有这么高效的 ...

  9. 布隆过滤器(Bloom Filter)详解——基于多hash的概率查找思想

    转自:http://www.cnblogs.com/haippy/archive/2012/07/13/2590351.html   布隆过滤器[1](Bloom Filter)是由布隆(Burton ...

随机推荐

  1. PHP 发送get请求

    PHP 发送get请求 file_get_contents 方法: $s = file_get_contents("http://apis.map.qq.com/ws/distance/v1 ...

  2. suseoj 1207: 大整数的乘法(java, 大数相乘, C/C++, 大数相乘)

    1207: 大整数的乘法 时间限制: 1 Sec  内存限制: 128 MB提交: 7  解决: 2[提交][状态][讨论版][命题人:liyuansong] 题目描述 求两个不超过200位的非负整数 ...

  3. nyoj 53-不高兴的小明 (遍历)

    53-不高兴的小明 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:28 submit:89 题目描述:    小明又出问题了.妈妈认为聪明的小明应该 ...

  4. 力扣(LeetCode)删除排序链表中的重复元素II 个人题解

    给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字. 思路和上一题类似(参考 力扣(LeetCode)删除排序链表中的重复元素 个人题解)) 只不过这里需要用到一个前 ...

  5. 逆向libbaiduprotect(二)

    首先要确保你所使用的gdb和gdbserver是配对的,最好(或必须)是sdk内相同platform(api level)下的gdb和gdbserver.否则你使用的gdb可能与运行测试机上的gdbs ...

  6. windows下自制动画层引擎 - 放两个demo

    一年前想写一个像cocoa那样,可以方便层动画开发的引擎,写着写着又逆向它的QuartzCore.framework,也就是CoreAnimation的底层,已经大半年没有搞windows这个引擎.大 ...

  7. vux组件的样式变量的使用

    使用x-header,查看文档发现有个样式变量,可以改变x-header的样式 这玩意怎么用呢? 1.在项目中创建一个.less样式文件,例如我这里是创建一个src/style/vux_theme.l ...

  8. nexus auto start

    cd /etc/init.d ln -s /opt/nexus/nexus-2.3.1-01/bin/jsw/linux-x86-64/nexus nexus chkconfig --add nexu ...

  9. PostGIS 爆管分析之找出上游阀门

    环境: Win10 ArcMap10.4(用于数据处理) postgresql9.4 postgis2.2.3 pgRouting2.3(postgresql插件) 说明: 继上一篇文章做了爆管分析找 ...

  10. Java虚拟机之栈

    一.程序计数器(寄存器):PCR 作用:记住下一条JVM指令的执行地址. 特点:①线程私有的 ②不会存在内存溢出 二.虚拟机栈 1.定义 虚拟机栈:线程运行所需要的内存空间. 栈帧:一个栈帧对应一个方 ...