切換語言為:簡體
40億訂單號,如何高效去重?

40億訂單號,如何高效去重?

  • 爱糖宝
  • 2024-07-29
  • 2071
  • 0
  • 0

前言

首先我們來看看如果要儲存40億QQ號需要多少記憶體?我們使用無符號整數儲存,一個整數需要4個位元組,那麼40億需要4*4000000000/1024/1024/1024≈15G,在業務中我們往往需要更多的空間。而且在Java中並不存在無符號整形,只有幾個操作無符號的靜態方法。

1GB = 1024MB,1MB = 1024KB,1KB = 1024B, 1B = 8b

很顯然這種儲存是不太優雅的,對於這種大資料量的去重,我們可以使用點陣圖Bitmap。

Bitmap

Bitmap,點陣圖,首先看它的名字,位元map,首先我們聽到map,一般都有去重的功能,bitmap聽名字就像使用bit儲存的map。確實,點陣圖是使用bit陣列表示的,它只儲存0或者1,因此我們可以把全部的QQ號放到點陣圖中,當index位置為1時表示已經存在。

40億訂單號,如何高效去重?

假如我們要判斷2924357571是否存在,那麼我們只需要看index為2924357571的值是否為1,如果為1則表示已經存在。

點陣圖使用1個位元表示一個數是否存在,那麼使用無符號整數表示QQ號,4位元組2^32-1是4294967295,記憶體需要4294967295/8/1024/1024≈512MB。

使用Java程式設計時,我們使用點陣圖一般是透過的redis,在redis中點陣圖常用的是以下三個命令:

命令 功能
SETBIT key offset value 設定指定offset位置的值,value只能是0或1
GETBIT key offset 獲取指定offset位置的值
BITCOUNT key start end 獲取start到end之間value為1的數量

演示

40億訂單號,如何高效去重?

其他作用

  1. 大資料量去重,Bitmap其極致的空間用在大資料量去重非常合適的,除了QQ號去重,我們還可以用在比如訂單號去重;爬取網站時URL去重,爬過的就不爬取了。

  2. 資料統計,比如線上人員統計,將線上人員id為偏移值,為1表示線上;影片統計,將全部影片的id為偏移儲存到Bitmap中。

  3. 布隆過濾器(BloomFilter),布隆過濾器的基礎就是使用的點陣圖,只不過布隆過濾器使用了多個雜湊函式處理,只有當全部的雜湊都為1,才表示這個值存在。

布隆過濾器

布隆過濾器一般會使用多個雜湊函式,計算出對應的hash對應多個位圖下標值,如果都為1,表示這個值存在。

40億訂單號,如何高效去重? 

例如hutool工具中布隆過濾器的實現類BitMapBloomFilter預設就提供了5個雜湊函式。

public BitMapBloomFilter(int m) {
    int mNum =NumberUtil.div(String.valueOf(m), String.valueOf(5)).intValue();
    long size = mNum * 1024 * 1024 * 8;
    
    filters = new BloomFilter[]{
       new DefaultFilter(size),
       new ELFFilter(size),
       new JSFilter(size),
       new PJWFilter(size),
       new SDBMFilter(size)
    };
}


優點:相較點陣圖,布隆過濾器使用多個hash演算法,我們就可以給字串或物件存進去計算hash了,不像點陣圖一樣只能使用整形數字看偏移位置是否為1。

缺點:可能產生雜湊衝突,如果判斷某個位置值為1,那麼可能是產生了雜湊衝突,所以,布隆過濾器會有一定誤差。

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.