最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot+Redis實(shí)現(xiàn)布隆過(guò)濾器的示例代碼

 更新時(shí)間:2022年03月17日 11:08:26   作者:小小陳丶  
本文主要介紹了SpringBoot+Redis實(shí)現(xiàn)布隆過(guò)濾器的示例代碼,文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

簡(jiǎn)述

關(guān)于布隆過(guò)濾器的詳細(xì)介紹,我在這里就不再贅述一遍了

我們首先知道:BloomFilter使用長(zhǎng)度為m bit的字節(jié)數(shù)組,使用k個(gè)hash函數(shù),增加一個(gè)元素: 通過(guò)k次hash將元素映射到字節(jié)數(shù)組中k個(gè)位置中,并設(shè)置對(duì)應(yīng)位置的字節(jié)為1。查詢?cè)厥欠翊嬖? 將元素k次hash得到k個(gè)位置,如果對(duì)應(yīng)k個(gè)位置的bit是1則認(rèn)為存在,反之則認(rèn)為不存在。

Guava 中已經(jīng)有具體的實(shí)現(xiàn),而在我們實(shí)際生產(chǎn)環(huán)境中,本地的存儲(chǔ)往往無(wú)法滿足我們實(shí)際的 需求。所以在這時(shí)候,就需要我們使用 redis 了。

Redis 安裝 Bloom Filter

git clone https://github.com/RedisLabsModules/redisbloom.git
cd redisbloom
make # 編譯

vi redis.conf
## 增加配置
loadmodule /usr/local/web/redis/RedisBloom-1.1.1/rebloom.so

##redis 重啟
#關(guān)閉
./redis-cli -h 127.0.0.1 -p 6379 shutdown
#啟動(dòng)
./redis-server ../redis.conf &

基本指令

#創(chuàng)建布隆過(guò)濾器,并設(shè)置一個(gè)期望的錯(cuò)誤率和初始大小
bf.reserve userid 0.01 100000
#往過(guò)濾器中添加元素
bf.add userid 'sbc@163.com'
#判斷指定key的value是否在bloomfilter里存在,存在:返回1,不存在:返回0
bf.exists userid 'sbc@163.com'

結(jié)合 SpingBoot

搭建一個(gè)簡(jiǎn)單的 springboot 框架

方式一

配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
? ? ? ? ?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
? ? ? ? xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
? ? <modelVersion>4.0.0</modelVersion>
? ? <groupId>com.bloom</groupId>
? ? <artifactId>test-bloomfilter</artifactId>
? ? <version>1.0-SNAPSHOT</version>
? ? <parent>
? ? ? ? <groupId>org.springframework.boot</groupId>
? ? ? ? <artifactId>spring-boot-starter-parent</artifactId>
? ? ? ? <version>1.5.8.RELEASE</version>
? ? ? ? <relativePath/> <!-- lookup parent from repository -->
? ? </parent>
? ? <dependencies>
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>org.springframework.boot</groupId>
? ? ? ? ? ? <artifactId>spring-boot-starter</artifactId>
? ? ? ? </dependency>
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>org.apache.commons</groupId>
? ? ? ? ? ? <artifactId>commons-lang3</artifactId>
? ? ? ? ? ? <version>3.0.1</version>
? ? ? ? </dependency>
? ? </dependencies>
</project>

redis本身對(duì)布隆過(guò)濾器就有一個(gè)很好地實(shí)現(xiàn),在 java 端,我們直接導(dǎo)入 redisson 的 jar包即可

<dependency>
? <groupId>org.redisson</groupId>
? <artifactId>redisson</artifactId>
? <version>3.8.2</version>
</dependency>

將 Redisson實(shí)例 注入 SpringIOC 容器中

@Configuration
public class RedissonConfig {

? ? @Value("${redisson.redis.address}")
? ? private String address;

? ? @Value("${redisson.redis.password}")
? ? private String password;

? ? @Bean
? ? public Config redissionConfig() {
? ? ? ? Config config = new Config();
? ? ? ? SingleServerConfig singleServerConfig = config.useSingleServer();
? ? ? ? singleServerConfig.setAddress(address);
? ? ? ? if (StringUtils.isNotEmpty(password)) {
? ? ? ? ? ? singleServerConfig.setPassword(password);
? ? ? ? }

? ? ? ? return config;
? ? }

? ? @Bean
? ? public RedissonClient redissonClient() {
? ? ? ? return Redisson.create(redissionConfig());
? ? }
}

配置文件

redisson.redis.address=redis://127.0.0.1:6379
redisson.redis.password=

最后測(cè)試我們的布隆過(guò)濾器

@SpringBootApplication
public class BloomApplication {
? ? public static void main(String[] args) {
? ? ? ? ConfigurableApplicationContext context = SpringApplication.run(BloomApplication.class, args);
? ? ? ? RedissonClient redisson = context.getBean(RedissonClient.class);
? ? ? ? RBloomFilter bf = redisson.getBloomFilter("test-bloom-filter");
? ? ? ? bf.tryInit(100000L, 0.03);
? ? ? ? Set<String> set = new HashSet<String>(1000);
? ? ? ? List<String> list = new ArrayList<String>(1000);
? ? ? //向布隆過(guò)濾器中填充數(shù)據(jù),為了測(cè)試真實(shí),我們記錄了 1000 個(gè) uuid,另外 9000個(gè)作為干擾數(shù)據(jù)
? ? ? ? for (int i = 0; i < 10000; i++) {
? ? ? ? ? ?String uuid = UUID.randomUUID().toString();
? ? ? ? ? if(i<1000){
? ? ? ? ? ? set.add(uuid);
? ? ? ? ? ? list.add(uuid);
? ? ? ? ? }
? ? ? ? ??
? ? ? ? ? ?bf.add(uuid);
? ? ? ? }

? ? ? ? int wrong = 0; // 布隆過(guò)濾器誤判的次數(shù)
? ? ? ? int right = 0;// 布隆過(guò)濾器正確次數(shù)
? ? ? ? for (int i = 0; i < 10000; i++) {
? ? ? ? ? ? String str = i % 10 == 0 ? list.get(i / 10) : UUID.randomUUID().toString();
? ? ? ? ? ? if (bf.contains(str)) {
? ? ? ? ? ? ? ? if (set.contains(str)) {
? ? ? ? ? ? ? ? ? ? right++;
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? wrong++;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }

? ? ? ? //right 為1000
? ? ? ? System.out.println("right:" + right);
? ? ? ? //因?yàn)檎`差率為3%,所以一萬(wàn)條數(shù)據(jù)wrong的值在30左右
? ? ? ? System.out.println("wrong:" + wrong);
? ? ? ?? ?//過(guò)濾器剩余空間大小
? ? ? ? System.out.println(bf.count());
? ? }
}

以上使我們使用 redisson 的使用方式,下面介紹一種比較原始的方式,使用lua腳本的方式

方式二

bf_add.lua

local bloomName = KEYS[1]
local value = KEYS[2]
local result = redis.call('BF.ADD',bloomName,value)
return result

bf_exist.lua

local bloomName = KEYS[1]
local value = KEYS[2]
 
local result = redis.call('BF.EXISTS',bloomName,value)
return result
@Service
public class RedisBloomFilterService {

? ? @Autowired
? ? private RedisTemplate redisTemplate;

? ? //我們依舊用剛剛的那個(gè)過(guò)濾器
? ? public static final String BLOOMFILTER_NAME = "test-bloom-filter";

? ? /**
? ? ?* 向布隆過(guò)濾器添加元素
? ? ?* @param str
? ? ?* @return
? ? ?*/
? ? public Boolean bloomAdd(String str) {
? ? ? ? DefaultRedisScript<Boolean> LuaScript = new DefaultRedisScript<Boolean>();
? ? ? ? LuaScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("bf_add.lua")));
? ? ? ? LuaScript.setResultType(Boolean.class);
? ? ? ? //封裝傳遞腳本參數(shù)
? ? ? ? List<String> params = new ArrayList<String>();
? ? ? ? params.add(BLOOMFILTER_NAME);
? ? ? ? params.add(str);
? ? ? ? return (Boolean) redisTemplate.execute(LuaScript, params);
? ? }

? ? /**
? ? ?* 檢驗(yàn)元素是否可能存在于布隆過(guò)濾器中 * @param id * @return
? ? ?*/
? ? public Boolean bloomExist(String str) {
? ? ? ? DefaultRedisScript<Boolean> LuaScript = new DefaultRedisScript<Boolean>();
? ? ? ? LuaScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("bf_exist.lua")));
? ? ? ? LuaScript.setResultType(Boolean.class);
? ? ? ? //封裝傳遞腳本參數(shù)
? ? ? ? ArrayList<String> params = new ArrayList<String>();
? ? ? ? params.add(BLOOMFILTER_NAME);
? ? ? ? params.add(String.valueOf(str));
? ? ? ? return (Boolean) redisTemplate.execute(LuaScript, params);
? ? }
}

最后我們還是用上面的啟動(dòng)器執(zhí)行測(cè)試代碼

@SpringBootApplication
public class BloomApplication {
? ? public static void main(String[] args) {
? ? ? ? ConfigurableApplicationContext context = SpringApplication.run(BloomApplication.class, args);
? ? ? ? RedisBloomFilterService filterService = context.getBean(RedisBloomFilterService.class);
? ? ? ? Set<String> set = new HashSet<String>(1000);
? ? ? ? List<String> list = new ArrayList<String>(1000);
? ? ? ? //向布隆過(guò)濾器中填充數(shù)據(jù),為了測(cè)試真實(shí),我們記錄了 1000 個(gè) uuid,另外 9000個(gè)作為干擾數(shù)據(jù)
? ? ? ? for (int i = 0; i < 10000; i++) {
? ? ? ? ? ? String uuid = UUID.randomUUID().toString();
? ? ? ? ? ? if (i < 1000) {
? ? ? ? ? ? ? ? set.add(uuid);
? ? ? ? ? ? ? ? list.add(uuid);
? ? ? ? ? ? }

? ? ? ? ? ? filterService.bloomAdd(uuid);
? ? ? ? }

? ? ? ? int wrong = 0; // 布隆過(guò)濾器誤判的次數(shù)
? ? ? ? int right = 0;// 布隆過(guò)濾器正確次數(shù)
? ? ? ? for (int i = 0; i < 10000; i++) {
? ? ? ? ? ? String str = i % 10 == 0 ? list.get(i / 10) : UUID.randomUUID().toString();
? ? ? ? ? ? if (filterService.bloomExist(str)) {
? ? ? ? ? ? ? ? if (set.contains(str)) {
? ? ? ? ? ? ? ? ? ? right++;
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? wrong++;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }

? ? ? ? //right 為1000
? ? ? ? System.out.println("right:" + right);
? ? ? ? //因?yàn)檎`差率為3%,所以一萬(wàn)條數(shù)據(jù)wrong的值在30左右
? ? ? ? System.out.println("wrong:" + wrong);
? ? }
}

相比而言,個(gè)人比較推薦第一種,實(shí)現(xiàn)的原理都是差不多,redis 官方已經(jīng)為我封裝好了執(zhí)行腳本,和相關(guān) api,用官方的會(huì)更好一點(diǎn)

到此這篇關(guān)于SpringBoot+Redis實(shí)現(xiàn)布隆過(guò)濾器的示例代碼的文章就介紹到這了,更多相關(guān)SpringBoot Redis布隆過(guò)濾器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot中restTemplate請(qǐng)求存在亂碼問(wèn)題的解決方法

    SpringBoot中restTemplate請(qǐng)求存在亂碼問(wèn)題的解決方法

    這篇文章主要介紹了SpringBoot中restTemplate請(qǐng)求存在亂碼問(wèn)題的解決方法,文中有相關(guān)的圖文和代碼示例供大家參考,對(duì)大家的解決問(wèn)題有一定的幫助,需要的朋友可以參考下
    2024-11-11
  • SpringMVC在多線程下請(qǐng)求頭獲取失敗問(wèn)題的解決方案

    SpringMVC在多線程下請(qǐng)求頭獲取失敗問(wèn)題的解決方案

    這篇文章主要介紹了我們就對(duì)多線程環(huán)境下使用SpringMVC中RequestContextHolder無(wú)法獲取請(qǐng)求的問(wèn)題進(jìn)行了深入的分析,并針對(duì)相關(guān)問(wèn)題給出了相應(yīng)的解決方案,需要的朋友可以參考下
    2024-08-08
  • Groovy編程入門(mén)攻略

    Groovy編程入門(mén)攻略

    這篇文章主要介紹了Groovy編程入門(mén)攻略,Groovy是一種同樣使用Java虛擬機(jī)的動(dòng)態(tài)語(yǔ)言,需要的朋友可以參考下
    2015-07-07
  • alibaba?seata服務(wù)端具體實(shí)現(xiàn)

    alibaba?seata服務(wù)端具體實(shí)現(xiàn)

    seata是來(lái)處理分布式服務(wù)之間互相調(diào)用的事務(wù)問(wèn)題,本文重點(diǎn)給大家介紹alibaba-seata實(shí)現(xiàn)方法,文中通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • Java基礎(chǔ)之Object類(lèi)詳解

    Java基礎(chǔ)之Object類(lèi)詳解

    這篇文章主要介紹了Java基礎(chǔ)之Object類(lèi)詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-05-05
  • JAVA微信掃碼支付模式二線上支付功能實(shí)現(xiàn)以及回調(diào)

    JAVA微信掃碼支付模式二線上支付功能實(shí)現(xiàn)以及回調(diào)

    本篇文章主要介紹了JAVA微信掃碼支付模式二線上支付功能實(shí)現(xiàn)以及回調(diào),這里整理了詳細(xì)的代碼,有需要的小伙伴可以參考下。
    2016-11-11
  • MyBatis編寫(xiě)嵌套子查詢的動(dòng)態(tài)SQL實(shí)踐詳解

    MyBatis編寫(xiě)嵌套子查詢的動(dòng)態(tài)SQL實(shí)踐詳解

    在Java生態(tài)中,MyBatis作為一款優(yōu)秀的ORM框架,廣泛應(yīng)用于數(shù)據(jù)庫(kù)操作,本文將深入探討如何在MyBatis中編寫(xiě)嵌套子查詢的動(dòng)態(tài)SQL,并結(jié)合實(shí)際案例分析其應(yīng)用場(chǎng)景與實(shí)現(xiàn)技巧
    2025-06-06
  • Maven實(shí)現(xiàn)把項(xiàng)目依賴的所有jar包都打到同一個(gè)jar中

    Maven實(shí)現(xiàn)把項(xiàng)目依賴的所有jar包都打到同一個(gè)jar中

    文章介紹了Maven打包項(xiàng)目的方法,包括使用shade-plugin和assembly-plugin插件配置、處理生成jar包中的簽名文件錯(cuò)誤、手動(dòng)生成可執(zhí)行jar包需指定主類(lèi),以及Linux下運(yùn)行jar包的多種方式(前臺(tái)、后臺(tái)、nohup等)
    2025-08-08
  • 利用Lambda表達(dá)式創(chuàng)建新線程案例

    利用Lambda表達(dá)式創(chuàng)建新線程案例

    這篇文章主要介紹了利用Lambda表達(dá)式創(chuàng)建新線程案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • java反射使用示例分享

    java反射使用示例分享

    這篇文章主要介紹了java反射使用示例,代碼很簡(jiǎn)單,需要的朋友可以參考下
    2014-02-02

最新評(píng)論

常州市| 香河县| 门源| 行唐县| 贡山| 元氏县| 崇礼县| 龙江县| 如皋市| 山东省| 富阳市| 凌源市| 湘乡市| 滁州市| 兴化市| 泊头市| 湟源县| 昌乐县| 兴安盟| 视频| 肇庆市| 梁山县| 宽城| 丽江市| 专栏| 清流县| 辰溪县| 景泰县| 益阳市| 水富县| 禄丰县| 南靖县| 莒南县| 阳泉市| 南涧| 克山县| 巴林左旗| 当阳市| 呼图壁县| 南阳市| 特克斯县|