国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

我把一千萬(wàn)次 SQL 校驗(yàn)干成了一次 Redis 布隆過(guò)濾——速度快到懷疑人生!

數(shù)據(jù)庫(kù) 其他數(shù)據(jù)庫(kù)
本文將從Bean的完整生命周期出發(fā),系統(tǒng)拆解其從元數(shù)據(jù)定義到資源銷毀的全流程節(jié)點(diǎn),詳解多樣化的創(chuàng)建方式與依賴注入邏輯,剖析不同作用域的適用場(chǎng)景。

在系統(tǒng)規(guī)模還很小時(shí),很多問(wèn)題都像不存在一樣。但當(dāng)用戶量突破數(shù)百萬(wàn)、上千萬(wàn)后,你會(huì)發(fā)現(xiàn)某些你從未關(guān)注過(guò)的“小細(xì)節(jié)”,會(huì)突然變成拖垮系統(tǒng)的幕后黑手。

我就踩過(guò)這樣一個(gè)坑——一個(gè)看似微不足道的用戶名重復(fù)校驗(yàn),差點(diǎn)把數(shù)據(jù)庫(kù)打到 CPU 100%。

這篇文章將帶你從“數(shù)據(jù)庫(kù)快燒掉了”,一路走到“靠 Redis Bloom Filter 穩(wěn)住場(chǎng)面”的完整過(guò)程,并給出 Spring Boot + Redis 最小可運(yùn)行 Demo。

數(shù)據(jù)庫(kù)第一次給我“吼”:你別查了行不行?

故事的開(kāi)始非常普通。

注冊(cè)接口需要校驗(yàn)用戶名是否已經(jīng)存在:

SELECT COUNT(*) FROM users WHERE username = 'praveen';

沒(méi)任何問(wèn)題。 沒(méi)任何難度。 也沒(méi)任何風(fēng)險(xiǎn)——直到用戶數(shù)量突破 10,000,000

然后,我的世界開(kāi)始變得不太美好:

  • CPU 一直拉滿
  • 請(qǐng)求響應(yīng)變慢
  • 數(shù)據(jù)庫(kù)連接池被瞬間占滿
  • 監(jiān)控圖上紅線一條接一條

讓我震驚的是,整個(gè)注冊(cè)流程最耗時(shí)的居然不是密碼校驗(yàn)、不是業(yè)務(wù)邏輯,而是這個(gè)看似 harmless 的“是否存在”查詢。

那一刻我終于明白了一件事:

數(shù)據(jù)庫(kù)天生不適合做 “我以前看過(guò)這個(gè)嗎?” 的判斷。

哪怕你給 username 建了索引,也一樣會(huì)觸發(fā):

  • I/O
  • 網(wǎng)絡(luò)往返
  • CPU 計(jì)算
  • 連接池爭(zhēng)搶

規(guī)模一大,這種查詢就是慢性毒藥。

我需要一個(gè) 能在訪問(wèn)數(shù)據(jù)庫(kù)之前做預(yù)篩選 的機(jī)制。

這時(shí),我遇見(jiàn)了 Bloom Filter:數(shù)據(jù)庫(kù)門口的保鏢。

如果你把數(shù)據(jù)庫(kù)比喻成一家酒吧,那 Bloom Filter 就像門口的保鏢。

它不需要認(rèn)識(shí)所有人,但它很快就能告訴你:

  • “這人肯定沒(méi)來(lái)過(guò)(不存在)”  —— 100% 準(zhǔn)確
  • “嗯?可能來(lái)過(guò),你進(jìn)去問(wèn)下(可能存在)” —— 有一定誤報(bào)率

這樣,大量根本不存在的用戶名 就會(huì)被擋在數(shù)據(jù)庫(kù)門外。

在實(shí)際測(cè)試中,它幫我過(guò)濾掉 90% ~ 99% 的數(shù)據(jù)庫(kù)查詢。

數(shù)據(jù)庫(kù):終于可以喘口氣了。

為什么我選擇 Redis 來(lái)承載 Bloom Filter?

Bloom Filter 本質(zhì)上是一個(gè)位數(shù)組 + 多個(gè)哈希函數(shù)。 Redis 天然適合作為它的容器,因?yàn)椋?/span>

  • Redis 全內(nèi)存存儲(chǔ),速度是納秒級(jí)別
  • 支持位圖操作(setbit / getbit)
  • 可以集群共享
  • 可以持久化

幾乎是為 Bloom Filter 量身定制的。

特別適合這些場(chǎng)景:

  • 用戶名 / 郵箱是否重復(fù)
  • 交易請(qǐng)求是否重復(fù)
  • 抓取系統(tǒng)去重
  • 爬蟲(chóng) URL 判重
  • 防垃圾消息

手把手帶你搭一個(gè)最小可用 Demo(Spring Boot + Redis)

接下來(lái),打造一個(gè)本地可跑的版本。

 Maven 依賴

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>


    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>


    <dependency>
        <groupId>io.lettuce.core</groupId>
        <artifactId>lettuce-core</artifactId>
    </dependency>
</dependencies>

本地安裝 Redis

Mac/Linux

brew install redis
redis-server

Windows

choco install redis
redis-server

配置文件 application.properties

spring.application.name=bloom-filter-demo
spring.redis.host=localhost
spring.redis.port=6379

核心邏輯:Bloom Filter 實(shí)現(xiàn)(已優(yōu)化代碼)

路徑:src/main/java/com/icoderoad/bloomfilter/service/BloomFilterService.java

package com.icoderoad.bloomfilter.service;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


import java.nio.charset.StandardCharsets;


@Service
public class BloomFilterService {


    // 位數(shù)組長(zhǎng)度
    private static final int SIZE = 1_000_000;


    // 多種哈希函數(shù)種子
    private static final int[] SEEDS = {7, 11, 13, 31, 37, 61};


    @Autowired
    private RedisTemplate<String, Object> redisTemplate;


    private static final String BLOOM_KEY = "username_bloom_filter";


    /** 添加元素 */
    public void add(String username) {
        for (int seed : SEEDS) {
            int hash = hash(username, seed);
            redisTemplate.opsForValue().setBit(BLOOM_KEY, hash, true);
        }
    }


    /** 判斷可能存在 */
    public boolean mightContain(String username) {
        for (int seed : SEEDS) {
            int hash = hash(username, seed);
            Boolean bit = redisTemplate.opsForValue().getBit(BLOOM_KEY, hash);
            if (bit == null || !bit) {
                return false; // 只要有一個(gè) bit 為 false,則一定不存在
            }
        }
        return true; // 所有 bit 都是 true,則可能存在
    }


    /** 哈希函數(shù) */
    private int hash(String value, int seed) {
        int result = 0;
        byte[] data = value.getBytes(StandardCharsets.UTF_8);
        for (byte b : data) {
            result = result * seed + b;
        }
        return Math.abs(result % SIZE);
    }
}

REST 接口

路徑:src/main/java/com/icoderoad/bloomfilter/controller/UsernameController.java

package com.icoderoad.bloomfilter.controller;


import com.icoderoad.bloomfilter.service.BloomFilterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;


@RestController
@RequestMapping("/usernames")
public class UsernameController {


    @Autowired
    private BloomFilterService bloomFilterService;


    @PostMapping("/add/{username}")
    public String addUsername(@PathVariable String username) {
        bloomFilterService.add(username);
        return "Username added: " + username;
    }


    @GetMapping("/check/{username}")
    public String checkUsername(@PathVariable String username) {
        boolean exists = bloomFilterService.mightContain(username);
        return exists ? "Username might exist!" : "Username definitely does not exist!";
    }
}

本地測(cè)試

添加用戶名

curl -X POST http://localhost:8080/usernames/add/praveencodes

檢查已添加用戶

curl http://localhost:8080/usernames/check/praveencodes

檢查不存在的用戶

curl http://localhost:8080/usernames/check/randomuser

內(nèi)部到底發(fā)生了什么?

過(guò)程非常簡(jiǎn)單但高效:

  1. 使用多個(gè)哈希函數(shù)對(duì) username 計(jì)算多個(gè) hash
  2. Redis 位數(shù)組對(duì)應(yīng)位置全部置 1
  3. 查詢時(shí)只檢查這些位是否都是 1
  4. 若都為 1 → 可能存在
  5. 若任意為 0 → 肯定不存在
  6. 如果判斷“不存在”,則不會(huì)訪問(wèn)數(shù)據(jù)庫(kù)

結(jié)果就是:

數(shù)據(jù)庫(kù)請(qǐng)求從 千萬(wàn)級(jí)下降到十萬(wàn)級(jí)QPS 提升數(shù)倍延遲從 3ms → 0.05ms

真實(shí)壓測(cè)結(jié)果(1000 萬(wàn)條數(shù)據(jù))

指標(biāo)

傳統(tǒng)數(shù)據(jù)庫(kù)

Bloom Filter 預(yù)篩選

單次查詢耗時(shí)

3–5 ms

0.05 ms

總 DB 查詢數(shù)

10,000,000

~100,000

內(nèi)存占用

僅幾 MB

Bloom Filter 就像一個(gè)超級(jí)前置緩存,把無(wú)意義的數(shù)據(jù)請(qǐng)求擋在數(shù)據(jù)庫(kù)之外。

Bloom Filter 的局限性

Bloom Filter 看似完美,但必須認(rèn)識(shí)這幾點(diǎn):

有誤報(bào)(False Positive)

  • 會(huì)誤判“存在”
  • 不會(huì)誤判“不存在” (即:不會(huì)漏掉實(shí)際存在的數(shù)據(jù))

 無(wú)法刪除

  • 位數(shù)組只有 0/1
  • 刪除會(huì)影響其他元素 (除非使用 Counting Bloom Filter)

 參數(shù)需要調(diào)優(yōu)

  • 位數(shù)組大小
  • 哈希函數(shù)數(shù)量
  • 容量規(guī)劃 都會(huì)影響誤報(bào)率與性能

結(jié)語(yǔ):唯一比 Bloom Filter 更可怕的,是忽視它

我們常常會(huì)把注意力放在復(fù)雜的優(yōu)化上,比如多線程、分庫(kù)分表、連接池調(diào)優(yōu)。 但真正讓系統(tǒng)崩潰的,有時(shí)就是這樣一個(gè)不起眼的存在校驗(yàn)。

Bloom Filter 的出現(xiàn)不是為了替代數(shù)據(jù)庫(kù),而是為了 保護(hù)數(shù)據(jù)庫(kù)。

它能把大量重復(fù)、無(wú)意義、可預(yù)判的請(qǐng)求擋掉, 讓數(shù)據(jù)庫(kù)把資源留給真正有價(jià)值的請(qǐng)求。

如果你的系統(tǒng)有以下情況:

  • 用戶量大
  • 去重操作頻繁
  • 需要高吞吐量
  • 在做 “是否存在” 判定

那 Bloom Filter 一定值得你立刻把它接入生產(chǎn)。

你不會(huì)后悔。 你的數(shù)據(jù)庫(kù)更不會(huì)。

責(zé)任編輯:武曉燕 來(lái)源: 路條編程
相關(guān)推薦

2024-01-05 09:04:35

隆過(guò)濾器數(shù)據(jù)結(jié)構(gòu)哈希函數(shù)

2019-03-22 15:15:25

Redis緩存擊穿雪崩效應(yīng)

2022-03-21 08:31:07

布隆過(guò)濾器Redis過(guò)濾器原理

2024-03-15 11:21:22

布隆過(guò)濾器數(shù)據(jù)庫(kù)數(shù)據(jù)

2024-09-18 10:08:37

2025-02-08 17:30:00

布隆過(guò)濾器數(shù)據(jù)結(jié)構(gòu)

2025-11-18 09:25:09

2025-04-30 08:47:41

2023-04-26 08:32:45

Redis布隆過(guò)濾器

2020-10-29 07:16:26

布隆過(guò)濾器場(chǎng)景

2023-01-31 08:19:53

二進(jìn)制元素數(shù)量

2024-11-11 14:57:56

JWTSession微服務(wù)

2020-10-21 12:10:30

訂單號(hào)Java代碼

2024-11-04 08:45:48

布隆過(guò)濾器元數(shù)據(jù)指紋值

2019-07-18 11:17:53

數(shù)據(jù)

2023-07-06 10:15:38

布隆過(guò)濾器優(yōu)化

2024-09-25 17:44:08

2025-01-23 00:00:00

Java布隆過(guò)濾器

2025-01-22 00:00:00

布隆過(guò)濾器二進(jìn)制

2024-10-09 15:54:38

布隆過(guò)濾器函數(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

一区二区在线观看网站| 精品中文字幕一区二区三区| 亚洲欧美另类小说| 鲁一鲁一鲁一鲁一澡| 国产毛片一区二区| 三年中国中文在线观看免费播放| 欧美aaaaaa午夜精品| 欧美极品一区二区| 欧美一区=区| 欧美人与物videos另类| 亚洲综合精品| 亚洲精品久久久久久一区二区| 一本色道久久综合亚洲精品不卡| 国产富婆一区二区三区| 国产一区二区三区四区老人| 亚洲综合中文字幕在线| 亚洲视频免费| 免费在线一区二区| 日本sm残虐另类| 中文字幕色呦呦| 99久久精品免费观看| 欧美少妇性生活视频| 国产精品丝袜91| 免费av片在线观看一道本| 亚洲精品视频在线看| 自拍av在线| 欧美日韩国产大片| 日韩伦理在线| 日韩最新av在线| 精品三级在线观看视频| 国产精品一区二区久久国产| 激情av一区| 国产高清不卡无码视频| 久久久久久日产精品| 黄色网免费看| 欧美日韩视频在线第一区 | 黄色av网站在线| 欧美sm极限捆绑bd| 欧美成人免费全部网站| 51午夜精品视频| 国内精品福利| 精品一区二区成人免费视频| 国产日韩av一区| 天堂成人在线| 亚洲老司机av| 国产成人黄色| 日韩一本精品| 国产精品激情偷乱一区二区∴| 欧美老女人性开放| 亚洲人成在线观| 国产探花在线精品| 色一情一乱一伦一区二区三区丨| 久久久久久久久久久久久女国产乱| 黄页网址在线观看| 日韩av影院在线观看| 亚洲欧美校园春色| 亚洲bbw性色大片| 亚洲色大成网站www久久九九| 黄色网址在线免费观看| 久热精品视频在线观看一区| 亚洲乱码电影| 日韩黄色片在线| 色老汉一区二区三区| 国产91欧美| 国产精品伊人日日| 亚洲国产精华液网站w| 超碰在线免费播放| 欧美中文字幕第一页| 六月丁香婷婷色狠狠久久| 日本免费看黄色| 亚洲一区第一页| 狠狠干综合网| 第四色亚洲色图| 亚洲欧美在线一区二区| 欧美不卡高清| 第四色亚洲色图| 亚洲视频日韩精品| 99视频一区| 国内精品卡一卡二卡三新区| 国产亚洲精品综合一区91| 91精品国产自产在线观看永久∴| 欧美一级在线看| 日韩欧美美女一区二区三区| 欧美精品久久久久久| 伊人成色综合网| 日韩一区二区三区三四区视频在线观看 | 亚洲午夜免费福利视频| 小明成人免费视频一区| 久久成人资源| 亚洲精品国产高清久久伦理二区| 日日夜夜天天综合| 成人动漫在线视频| 一区二区三区四区激情| 精品九九久久| 亚洲国产精品久久久久久女王| 欧美日韩在线第一页| 大奶一区二区三区| 国产女教师bbwbbwbbw| 91精品国产91久久综合桃花 | 国产精品成人v| 久久精品亚洲国产奇米99| 手机在线理论片| 久久久水蜜桃| 91九色最新地址| 久久国产电影| 国产一级黄色电影| 久久久久久噜噜噜久久久精品| 国产成人免费高清| 性国裸体高清亚洲| 亚洲在线欧美| 欧美mv日韩mv| 日韩精品亚洲一区二区三区免费| 国产黄色在线| 国产成人精品日本亚洲11| 舔着乳尖日韩一区| 欧美独立站高清久久| 黄色av观看| 国产成人精品一区二区在线| 亚洲人亚洲人成电影网站色| 林ゆな中文字幕一区二区| 热久久精品国产| 久热99视频在线观看| 久久久久久**毛片大全| 国产精品亚洲四区在线观看| 国产91在线免费| 精品国产欧美一区二区五十路| 成a人片亚洲日本久久| 亚洲色图图片| 亚洲免费av一区二区三区| 国内精品一区二区三区| 亚洲三级小视频| 四季av在线一区二区三区| 尤物视频在线观看| 狠狠色伊人亚洲综合网站色 | 成人三级黄色免费网站| 999国产在线| 欧美人xxxx| 美女网站色91| 播放一区二区| 成年人免费大片| 国产大片精品免费永久看nba| 亚洲精品国产品国语在线app| 日韩av有码| 日本免费在线视频| 亚洲永久激情精品| 久久亚洲成人精品| 一区二区在线免费| 综合天堂久久久久久久| 免费av在线网站| 日韩人妻一区二区三区蜜桃视频| 久久精品国产欧美激情| 亚洲视频一二三区| 欧美淫片网站| 免费成人在线电影| 丰满人妻中伦妇伦精品app| 韩剧1988免费观看全集| 天天色图综合网| 日韩在线一区二区三区| av在线一区不卡| av高清日电影| 欧美xxxx黑人又粗又长精品| 亚洲最大中文字幕| 亚洲一区在线看| 青青草成人在线观看| 久久一级大片| 国产综合视频一区二区三区免费| 亚洲欧美在线网| 亚州国产精品久久久| 欧美日韩国产色站一区二区三区| 黑人巨大精品欧美一区| 全球av集中精品导航福利| 大乳在线免费观看| 久久成人免费观看| 亚洲一区二区三区四区在线播放| 亚洲国产精品va在线| 国产精品白丝在线| 日韩精彩视频在线观看| 日本精品视频| √天堂资源地址在线官网| 波多野结衣乳巨码无在线| 91亚洲va在线va天堂va国| 亚洲天堂av在线免费观看| 亚洲欧美另类小说视频| 另类人妖一区二区av| 99亚洲乱人伦aⅴ精品| 伦xxxx在线| 丰满少妇又爽又紧又丰满69| 久久久久久久久久久一区| 欧美国产日韩视频| 欧美一级欧美三级| 中文字幕亚洲精品在线观看 | 国产98在线|日韩| www国产91| 欧美亚洲国产怡红院影院| 91在线视频在线| 伊人影院久久| 欧美jizz19性欧美| 在线免费日韩片| av免费观看一区二区| 999精彩视频|