成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試官問,如何在十億級別用戶中檢查用戶名是否存在?

數據庫 其他數據庫
Redis 布隆過濾器的方案為大數據量下唯一性驗證提供了一種基于內存的高效解決方案,它需要在內存消耗和錯誤率之間取得一個平衡點。當然布隆過濾器還有更多應用場景,比如防止緩存穿透、防止惡意訪問等。

前言

不知道大家有沒有留意過,在使用一些app注冊的時候,提示你用戶名已經被占用了,需要更換一個,這是如何實現的呢?你可能想這不是很簡單嗎,去數據庫里查一下有沒有不就行了嗎,那么假如用戶數量很多,達到數億級別呢,這又該如何是好?

數據庫方案

圖片

第一種方案就是查數據庫的方案,大家都能夠想到,代碼如下:

public class UsernameUniquenessChecker {
    private static final String DB_URL = "jdbc:mysql://localhost:3306/your_database";
    private static final String DB_USER = "your_username";
    private static final String DB_PASSWORD = "your_password";

    public static boolean isUsernameUnique(String username) {
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            String sql = "SELECT COUNT(*) FROM users WHERE username = ?";
            try (PreparedStatement stmt = conn.prepareStatement(sql)) {
                stmt.setString(1, username);
                try (ResultSet rs = stmt.executeQuery()) {
                    if (rs.next()) {
                        int count = rs.getInt(1);
                        return count == 0; // If count is 0, username is unique
                    }
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false; // In case of an error, consider the username as non-unique
    }

    public static void main(String[] args) {
        String desiredUsername = "new_user";
        boolean isUnique = isUsernameUnique(desiredUsername);
        if (isUnique) {
            System.out.println("Username '" + desiredUsername + "' is unique. Proceed with registration.");
        } else {
            System.out.println("Username '" + desiredUsername + "' is already in use. Choose a different one.");
        }
    }
}

這種方法會帶來如下問題:

  1. 性能問題,延遲高 。 如果數據量很大,查詢速度慢。另外,數據庫查詢涉及應用程序服務器和數據庫服務器之間的網絡通信。建立連接、發送查詢和接收響應所需的時間也會導致延遲。
  2. 數據庫負載過高。頻繁執行 SELECT 查詢來檢查用戶名唯一性,每個查詢需要數據庫資源,包括CPU和I/O。
  3. 可擴展性差。數據庫對并發連接和資源有限制。如果注冊率繼續增長,數據庫服務器可能難以處理數量增加的傳入請求。垂直擴展數據庫(向單個服務器添加更多資源)可能成本高昂并且可能有限制。

緩存方案

為了解決數據庫調用用戶名唯一性檢查的性能問題,引入了高效的Redis緩存。

圖片圖片

public class UsernameCache {

    private static final String REDIS_HOST = "localhost";
    private static final int REDIS_PORT = 6379; 
    private static final int CACHE_EXPIRATION_SECONDS = 3600; 

    private static JedisPool jedisPool;

    // Initialize the Redis connection pool
    static {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        jedisPool = new JedisPool(poolConfig, REDIS_HOST, REDIS_PORT);
    }

    // Method to check if a username is unique using the Redis cache
    public static boolean isUsernameUnique(String username) {
        try (Jedis jedis = jedisPool.getResource()) {
            // Check if the username exists in the Redis cache
            if (jedis.sismember("usernames", username)) {
                return false; // Username is not unique
            }
        } catch (Exception e) {
            e.printStackTrace();
            // Handle exceptions or fallback to database query if Redis is unavailable
        }
        return true; // Username is unique (not found in cache)
    }

    // Method to add a username to the Redis cache
    public static void addToCache(String username) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.sadd("usernames", username); // Add the username to the cache set
            jedis.expire("usernames", CACHE_EXPIRATION_SECONDS); // Set expiration time for the cache
        } catch (Exception e) {
            e.printStackTrace();
            // Handle exceptions if Redis cache update fails
        }
    }

    // Cleanup and close the Redis connection pool
    public static void close() {
        jedisPool.close();
    }
}

這個方案最大的問題就是內存占用過大,假如每個用戶名需要大約 20 字節的內存。你想要存儲10億個用戶名的話,就需要20G的內存。

總內存 = 每條記錄的內存使用量 * 記錄數 = 20 字節/記錄 * 1,000,000,000 條記錄 = 20,000,000,000 字節 = 20,000,000 KB = 20,000 MB = 20 GB

布隆過濾器方案

直接緩存判斷內存占用過大,有沒有什么更好的辦法呢?布隆過濾器就是很好的一個選擇。

那究竟什么布隆過濾器呢?

布隆過濾器(Bloom Filter)是一種數據結構,用于快速檢查一個元素是否存在于一個大型數據集中,通常用于在某些情況下快速過濾掉不可能存在的元素,以減少后續更昂貴的查詢操作。布隆過濾器的主要優點是它可以提供快速的查找和插入操作,并且在內存占用方面非常高效。

具體的實現原理和數據結構如下圖所示:

圖片圖片

布隆過濾器的核心思想是使用一個位數組(bit array)和一組哈希函數。

  • 位數組(Bit Array) :布隆過濾器使用一個包含大量位的數組,通常初始化為全0。每個位可以存儲兩個值,通常是0或1。這些位被用來表示元素的存在或可能的存在。
  • 哈希函數(Hash Functions) :布隆過濾器使用多個哈希函數,每個哈希函數可以將輸入元素映射到位數組的一個或多個位置。這些哈希函數必須是獨立且具有均勻分布特性。

那么具體是怎么做的呢?

  • 添加元素:如上圖所示,當將字符串“xuyang”,“alvin”插入布隆過濾器時,通過多個哈希函數將元素映射到位數組的多個位置,然后將這些位置的位設置為1。
  • 查詢元素:當要檢查一個元素是否存在于布隆過濾器中時,通過相同的哈希函數將元素映射到位數組的相應位置,然后檢查這些位置的位是否都為1。如果有任何一個位為0,那么可以確定元素不存在于數據集中。但如果所有位都是1,元素可能存在于數據集中,但也可能是誤判。

本身redis支持布隆過濾器的數據結構,我們用代碼簡單實現了解一下:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class BloomFilterExample {
    public static void main(String[] args) {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        JedisPool jedisPool = new JedisPool(poolConfig, "localhost", 6379);

        try (Jedis jedis = jedisPool.getResource()) {
            // 創建一個名為 "usernameFilter" 的布隆過濾器,需要指定預計的元素數量和期望的誤差率
            jedis.bfCreate("usernameFilter", 10000000, 0.01);
            
            // 將用戶名添加到布隆過濾器
            jedis.bfAdd("usernameFilter", "alvin");
            
            // 檢查用戶名是否已經存在
            boolean exists = jedis.bfExists("usernameFilter", "alvin");
            System.out.println("Username exists: " + exists);
        }
    }
}

在上述示例中,我們首先創建一個名為 "usernameFilter" 的布隆過濾器,然后使用 bfAdd 將用戶名添加到布隆過濾器中。最后,使用 bfExists 檢查用戶名是否已經存在。

優點:

  • 節約內存空間,相比使用哈希表等數據結構,布隆過濾器通常需要更少的內存空間,因為它不存儲實際元素,而只存儲元素的哈希值。如果以 0.001 誤差概率存儲 10 億條記錄,只需要 1.67 GB 內存,對比原來的20G,大大的減少了。
  • 高效的查找, 布隆過濾器可以在常數時間內(O(1))快速查找一個元素是否存在于集合中,無需遍歷整個集合。

缺點:

  • 誤判率存在:布隆過濾器在判斷元素是否存在時,有一定的誤判率。這意味著在某些情況下,它可能會錯誤地報告元素存在,但不會錯誤地報告元素不存在。
  • 不能刪除元素:布隆過濾器通常不支持從集合中刪除元素,因為刪除一個元素會影響其他元素的哈希值,增加了誤判率。

總結

Redis 布隆過濾器的方案為大數據量下唯一性驗證提供了一種基于內存的高效解決方案,它需要在內存消耗和錯誤率之間取得一個平衡點。當然布隆過濾器還有更多應用場景,比如防止緩存穿透、防止惡意訪問等。

責任編輯:武曉燕 來源: JAVA旭陽
相關推薦

2010-10-29 11:51:30

oracle用戶名

2022-01-17 13:34:45

MySQLLinux數據庫

2010-09-27 14:48:12

SQL用戶名

2021-11-08 09:18:01

CAS面試場景

2021-12-25 22:31:10

MarkWord面試synchronize

2009-10-21 16:34:03

Oracle用戶名重建索引

2019-08-26 19:24:55

Podman容器Linux

2021-04-21 09:28:17

字節面試官SetTimeout

2018-07-20 14:20:24

Linux用戶組管理員

2011-05-26 10:11:24

Oracle數據庫索引

2010-08-23 15:06:52

發問

2021-12-16 18:38:13

面試Synchronize

2021-01-06 05:36:25

拉鏈表數倉數據

2022-01-05 09:55:26

asynawait前端

2021-10-04 08:26:10

用戶名密碼信息

2025-03-10 03:00:00

CSSline字體

2022-06-24 08:48:47

用戶名密碼登錄

2013-01-04 17:51:28

Android開發SharedPrefe解析用戶名

2009-08-05 13:32:07

Oracle按用戶名重

2015-08-13 10:29:12

面試面試官
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久久精 | 婷婷成人在线 | 热99| 极品粉嫩国产48尤物在线播放 | 亚洲精品久久久一区二区三区 | 黄色成人在线观看 | 中文字幕精品一区二区三区精品 | 国产农村妇女毛片精品久久麻豆 | 中文字幕日韩一区 | 免费黄色a级毛片 | 国产精品视频免费观看 | 一级特黄色毛片 | 亚洲精品一区二区在线观看 | 在线日韩福利 | 四虎最新视频 | 亚洲 精品 综合 精品 自拍 | 国内精品视频在线观看 | 国产一区| 中文字幕乱码一区二区三区 | av黄色在线| 国产乱码高清区二区三区在线 | 日韩欧美综合 | 91一区| 天天草天天 | 丁香一区二区 | 亚洲区在线 | 综合久久一区 | 在线视频一区二区 | 九色91视频 | 国产一区二区三区免费观看在线 | 男人av在线 | 日韩在线视频一区 | 成人av一区二区三区 | 欧美日韩一二三区 | 亚洲精品久久久久久久久久吃药 | 亚洲精品在线看 | 国产成人综合在线 | 国产一级淫片a直接免费看 免费a网站 | 欧美一级在线观看 | 国产色| 日韩久久精品视频 |