基于Redis的BloomFilter实现
前言
最近在研究布隆过滤器(如果不了解什么是布隆过滤器的,推荐看这篇如何判断一个元素在亿级数据中是否存在?了解),发现Guava提供了封装好的类,但是只能单机使用,一般现在的应用都是部署在分布式系统的,所以想找个可以在分布式系统下使用的布隆过滤器,找了半天只找到一个基于redis开发的模块项目ReBloom,但是这个是需要额外安装的,而且文档里只说了怎么在docker下运行,没研究过docker所以放弃了。后来找到一篇博客讲怎么利用布隆过滤器统计消息未读数的(博客地址不记得了,是一位淘宝同学写的),博客最后放了一份整合redis和bloomFilter的代码demo,详见BloomFilter.java,看了下实现比较简单,但是使用方式不是我想要的,所以参考着自己整理了一份。
BloomFilterHelper
package com.doodl6.springmvc.service.cache.redis;import com.google.common.base.Preconditions;
import com.google.common.hash.Funnel;
import com.google.common.hash.Hashing;public class BloomFilterHelper<T> {private int numHashFunctions;private int bitSize;private Funnel<T> funnel;public BloomFilterHelper(Funnel<T> funnel, int expectedInsertions, double fpp) {Preconditions.checkArgument(funnel != null, "funnel不能为空");this.funnel = funnel;bitSize = optimalNumOfBits(expectedInsertions, fpp);numHashFunctions = optimalNumOfHashFunctions(expectedInsertions, bitSize);}int[] murmurHashOffset(T value) {int[] offset = new int[numHashFunctions];long hash64 = Hashing.murmur3_128().hashObject(value, funnel).asLong();int hash1 = (int) hash64;int hash2 = (int) (hash64 >>> 32);for (int i = 1; i <= numHashFunctions; i++) {int nextHash = hash1 + i * hash2;if (nextHash < 0) {nextHash = ~nextHash;}offset[i - 1] = nextHash % bitSize;}return offset;}/*** 计算bit数组长度*/private int optimalNumOfBits(long n, double p) {if (p == 0) {p = Double.MIN_VALUE;}return (int) (-n * Math.log(p) / (Math.log(2) * Math.log(2)));}/*** 计算hash方法执行次数*/private int optimalNumOfHashFunctions(long n, long m) {return Math.max(1, (int) Math.round((double) m / n * Math.log(2)));}
}
BloomFilterHelper是实现功能的关键,包含了计算bitmap的核心算法,其实大部分代码都是来源于Guava库里面的BloomFilterStrategies类,但是因为这个类是专门为Guava的BloomFilter类使用的,所以没有对外暴露一些重要的算法逻辑。
再来看怎么结合redis一起使用BloomFilterHelper
RedisService
package com.doodl6.springmvc.service.cache.redis;import com.google.common.base.Preconditions;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.TimeUnit;@Service
public class RedisService {@Resourceprivate RedisTemplate<String, Object> redisTemplate;/*** 根据给定的布隆过滤器添加值*/public <T> void addByBloomFilter(BloomFilterHelper<T> bloomFilterHelper, String key, T value) {Preconditions.checkArgument(bloomFilterHelper != null, "bloomFilterHelper不能为空");int[] offset = bloomFilterHelper.murmurHashOffset(value);for (int i : offset) {redisTemplate.opsForValue().setBit(key, i, true);}}/*** 根据给定的布隆过滤器判断值是否存在*/public <T> boolean includeByBloomFilter(BloomFilterHelper<T> bloomFilterHelper, String key, T value) {Preconditions.checkArgument(bloomFilterHelper != null, "bloomFilterHelper不能为空");int[] offset = bloomFilterHelper.murmurHashOffset(value);for (int i : offset) {if (!redisTemplate.opsForValue().getBit(key, i)) {return false;}}return true;}
}
RedisService很简单,只有两个方法
addByBloomFilter,往redis里面添加元素
includeByBloomFilter,检查元素是否在redis bloomFilter里面
这里redis的客户端使用的是spring-data-redis封装的,可以在我的项目SpringMVC-Project中查看完整的使用代码。
基于Redis的BloomFilter实现相关推荐
- 基于 Redis 实现分布式锁思考
以下文章来源方志朋的博客,回复"666"获面试宝典 来源:blog.csdn.net/xuan_lu/article/details/111600302 分布式锁 基于redis实 ...
- nx set 怎么实现的原子性_基于Redis的分布式锁实现
前言 本篇文章主要介绍基于Redis的分布式锁实现到底是怎么一回事,其中参考了许多大佬写的文章,算是对分布式锁做一个总结 分布式锁概览 在多线程的环境下,为了保证一个代码块在同一时间只能由一个线程访问 ...
- 大神级教程!300分钟撸一个基于Redis 6.0 版本的高并发架构
刚好原先公司搞职位调整,我不太满意,赶上这波金三银四的面试浪潮,干了也有5年的后端开发了,不是大神也是有实战经验的,我就自信满满地去面了几家大厂,结果就遇到... 面试官这夺命连环12问,谁顶得住? ...
- 基于Redis的分布式锁和Redlock算法
来自:后端技术指南针 1 前言 今天开始来和大家一起学习一下Redis实际应用篇,会写几个Redis的常见应用. 在我看来Redis最为典型的应用就是作为分布式缓存系统,其他的一些应用本质上并不是杀手 ...
- 从0设计一个基于Redis的锁服务
作者:温灏,后端研发,专注于Python和Go,对分布式系统感兴趣,本文系作者投稿,有兴趣投稿的同学,请后台回复[投稿] 由于微服务大行其道,服务之间的协调工作变得越来越重要.今天来简单说一下如何搭建 ...
- python分布式任务调度_Python使用Celery分布式异步队列/任务调度(基于Redis) - pytorch中文网...
今天使用爬虫有些耗时较长,需要使用任务调度,Celery是Python开发的分布式任务调度模块,Celery本身不含消息服务,它使用第三方消息服务来传递任务,目前,Celery支持的消息服务有Rabb ...
- redistemplate分布式锁实现_基于 Redis SETNX 实现分布式锁
环境与配置 Redis 任意版本即可 SpringBoot 任意版本即可,但是需要依赖 spring-boot-starter-data-redis <dependency><gro ...
- 基于redis的cas集群配置(转)
1.cas ticket统一存储 做cas集群首先需要将ticket拿出来,做统一存储,以便每个节点访问到的数据一致.官方提供基于memcached的方案,由于项目需要,需要做计入redis,根据官方 ...
- redis系列:基于redis的分布式锁
一.介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分为两部分,一个是单机环境, ...
最新文章
- 爬虫python下载-如何用Python爬虫实现百度图片自动下载?
- django_rest_framework—路由器机制
- linux服务器登录时慢出现卡顿
- JavaScript数组sort方法(数组排序)
- C语言第三节关键字、标识符、注释
- 2500万美元和AI专家!谷歌出钱出人,要用AI做“对社会有益”的事情
- 网站搭建 (第03天) 分页功能
- 最近的shell脚本(updating)
- java发送邮件工具类
- 首次项目经验总结(一)
- 2020大数据技术体系结构图,你值得拥有
- 调查问卷或量表数据的一般处理与SPSS统计分析
- 读 稻盛和夫《干法》
- 2003sql php_Windows Server 2003下安装PHP +mssql2000
- 中国眼部护理产品市场趋势报告、技术动态创新及市场预测
- MI200e电力线通讯
- 王兴:8年时间,我对商业的思考
- HIHO#1245 : 王胖浩与三角形
- Netflix Movies and TV Shows(Netflix影视剧数据集)
- 有苦有乐的算法 --- 自定义一个栈,实现压栈(push)、弹栈(pop)、获取站内最小值(getmin)
热门文章
- 人脸识别,验证,登录开发 (三)
- Java 获取本地时间与网络时间
- 因计算机丢失d3dx9-30,Win10玩仙剑5提示d3dx9_30.dll文件丢失的解决方法
- 图像,log处理的一点经验
- Spring5 Unsupported class解决方法:probably due to a new Java class file version that is supported yet
- Android Sandbox(沙箱)开源工具介绍
- html5账号秘密,JavaScript有关的10个秘密和怪癖
- 阿里云 IoT 企业物联网平台 MQTT 通讯模式
- html5安卓机判断刘海屏,Android判断是否为刘海屏
- excel如何快速提取身份证的出生日期