亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > Redis > 正文

Redis精確去重計數方法(咆哮位圖)

2020-10-28 21:30:15
字體:
來源:轉載
供稿:網友

前言

如果要統計一篇文章的閱讀量,可以直接使用 Redis 的 incr 指令來完成。如果要求閱讀量必須按用戶去重,那就可以使用 set 來記錄閱讀了這篇文章的所有用戶 id,獲取 set 集合的長度就是去重閱讀量。但是如果爆款文章閱讀量太大,set 會浪費太多存儲空間。這時候我們就要使用 Redis 提供的 HyperLogLog 數據結構來代替 set,它只會占用最多 12k 的存儲空間就可以完成海量的去重統計。但是它犧牲了準確度,它是模糊計數,誤差率約為 0.81%。

那么有沒有一種不怎么浪費空間的精確計數方法呢?我們首先想到的就是位圖,可以使用位圖的一個位來表示一個用戶id。如果一個用戶id是32字節,那么使用位圖就只需要占用 1/256 的空間就可以完成精確計數。但是如何將用戶id映射到位圖的位置呢?如果用戶id是連續的整數這很好辦,但是通常用戶系統的用戶id并不是整數,而是字符串或者是有一定隨機性的大整數。

我們可以強行給每個用戶id賦予一個整數序列,然后將用戶id和整數的對應關系存在redis中。

$next_user_id = incr user_id_seqset user_id_xxx $next_user_id$next_user_id = incr user_id_seqset user_id_yyy $next_user_id$next_user_id = incr user_id_seqset user_id_zzz $next_user_id

這里你也許會提出疑問,你說是為了節省空間,這里存儲用戶id和整數的映射關系就不浪費空間了么?這個問題提的很好,但是同時我們也要看到這個映射關系是可以復用的,它可以統計所有文章的閱讀量,還可以統計簽到用戶的日活、月活,還可以用在很多其它的需要用戶去重的統計場合中。所謂「功在當代,利在千秋」就是這個意思。

有了這個映射關系,我們就很容易構造出每一篇文章的閱讀打點位圖,來一個用戶,就將相應位圖中相應的位置為一。如果位從0變成1,那么就可以給閱讀數加1。這樣就可以很方便的獲得文章的閱讀數。

而且我們還可以動態計算閱讀了兩篇文章的公共用戶量有多少?將兩個位圖做一下 AND 計算,然后統計位圖中位 1 的個數。同樣,還可以有 OR 計算、XOR 計算等等都是可行的。

問題又來了!Redis 的位圖是密集位圖,什么意思呢?如果有一個很大的位圖,它只有最后一個位是 1,其它都是零,這個位圖還是會占用全部的內存空間,這就不是一般的浪費了。你可以想象大部分文章的閱讀量都不大,但是它們的占用空間卻是很接近的,和哪些爆款文章占據的內存差不多。

看來這個方案行不通,我們需要想想其它方案!這時咆哮位圖(RoaringBitmap)來了。

它將整個大位圖進行了分塊,如果整個塊都是零,那么這整個塊就不用存了。但是如果位1比較分散,每個塊里面都有1,雖然單個塊里的1很少,這樣只進行分塊還是不夠的,那該怎么辦呢?我們再想想,對于單個塊,是不是可以繼續優化?如果單個塊內部位 1 個數量很少,我們可以只存儲所有位1的塊內偏移量(整數),也就是存一個整數列表,那么塊內的存儲也可以降下來。這就是單個塊位圖的稀疏存儲形式 ―― 存儲偏移量整數列表。只有單塊內的位1超過了一個閾值,才會一次性將稀疏存儲轉換為密集存儲。

咆哮位圖除了可以大幅節約空間之外,還會降低 AND、OR 等位運算的計算效率。以前需要計算整個位圖,現在只需要計算部分塊。如果塊內非常稀疏,那么只需要對這些小整數列表進行集合的 AND、OR 運算,如是計算量還能繼續減輕。

這里既不是用空間換時間,也沒有用時間換空間,而是用邏輯的復雜度同時換取了空間和時間。

咆哮位圖的位長最大為 2^32,對應的空間為 512M(普通位圖),位偏移被分割成高 16 位和低 16 位,高 16 位表示塊偏移,低16位表示塊內位置,單個塊可以表達 64k 的位長,也就是 8K 字節。最多會有64k個塊?,F代處理器的 L1 緩存普遍要大于 8K,這樣可以保證單個塊都可以全部放入 L1 Cache,可以顯著提升性能。

如果單個塊所有的位全是零,那么它就不需要存儲。具體某個塊是否存在也可以是用位圖來表達,當塊很少時,用整數列表表示,當塊多了就可以轉換成普通位圖。整數列表占用的空間少,它還有類似于 ArrayList 的動態擴容機制避免反復擴容復制數組內容。當列表中的數字超出4096個時,會立即轉變成普通位圖。

用來表達塊是否存在的數據結構和表達單個塊數據的結構可以是同一個,因為塊是否存在本質上也是 0 和 1,就是普通的位標志。

但是 Redis 并沒有原生支持咆哮位圖這個數據結構???我們該如何使用呢?

Redis 確實沒有原生的,但是咆哮位圖的 Redis Module 有。

github.com/aviggiano/r…

這個項目的 star 數量并不是很多,我們來看看它的官方性能對比

OP TIME/OP (us) ST.DEV. (us)
R.SETBIT 31.89 28.49
SETBIT 29.98 29.23
R.GETBIT 29.90 14.60
GETBIT 28.63 14.58
R.BITCOUNT 32.13 0.10
BITCOUNT 192.38 0.96
R.BITPOS 70.27 0.14
BITPOS 87.70 0.62
R.BITOP NOT 156.66 3.15
BITOP NOT 364.46 5.62
R.BITOP AND 81.56 0.48
BITOP AND 492.97 8.32
R.BITOP OR 107.03 2.44
BITOP OR 461.68 8.42
R.BITOP XOR 69.07 2.82
BITOP XOR 440.75 7.90

很明顯這里對比的是稀疏位圖,只有稀疏位圖才可以呈現出這樣好看的數字。如果是密集位圖,咆哮位圖的性能肯定要稍弱于普通位圖,但是通常也不會弱太多。

下面我們來觀察一下源代碼看看它的內部結構是怎樣的

// 單個塊typedef struct roaring_array_s { int32_t size; int32_t allocation_size; void **containers; // 指向整數數組或者普通位圖 uint16_t *keys; uint8_t *typecodes; uint8_t flags;} roaring_array_t;// 所有塊typedef struct roaring_bitmap_s { roaring_array_t high_low_container;} roaring_bitmap_t;

很明顯可以看到塊存在與否和塊內數據都是使用同樣的數據結構表達的,它們都是 roaring_bitmap_t。這個結構里面有多種編碼形式,類型使用 typecodes 字段來表示。

#define BITSET_CONTAINER_TYPE_CODE 1#define ARRAY_CONTAINER_TYPE_CODE 2#define RUN_CONTAINER_TYPE_CODE 3#define SHARED_CONTAINER_TYPE_CODE 4

看到這里的類型定義,我們發現它不止前面提到的普通位圖和數組列表兩種形式,還有 RUN 和 SHARED 這兩種類型。RUN 形式是位圖的壓縮形式,比如連續的幾個位 101,102,103,104,105,106,107,108,109 表示成 RUN 后就是 101,8(1 后面是 8 個自增的整數),這樣在空間上就可以明顯壓縮不少。在正常情況下咆哮位圖內部沒有 RUN 類型的塊。只有顯示調用了咆哮位圖的優化 API 才會轉換成 RUN 格式,這個 API 是 roaring_bitmap_run_optimize。

而 SHARED 類型用于在多個咆哮位圖之間共享塊,它還提供了寫復制功能。當這個塊被修改時將會復制出新的一份。
咆哮位圖的計算邏輯還有更多的細節,我們后面有空再繼續介紹。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
尤物九九久久国产精品的分类| 45www国产精品网站| 亚洲国产黄色片| 日日骚av一区| 91精品国产免费久久久久久| 国产欧美欧洲在线观看| 国产成人综合一区二区三区| 日韩精品极品在线观看播放免费视频| 亚洲影视九九影院在线观看| 日本高清+成人网在线观看| 国产日产亚洲精品| 另类天堂视频在线观看| 成人av在线亚洲| 91社影院在线观看| 久久中文字幕视频| 亚洲国产古装精品网站| 欧美精品在线播放| 欧美激情国内偷拍| 在线丨暗呦小u女国产精品| 久久久伊人欧美| 国产精品美女www| 亚洲国产日韩一区| 69久久夜色精品国产69乱青草| 欧美日韩色婷婷| 国产成人综合av| 欧美日韩午夜视频在线观看| 欧美激情亚洲视频| 久久在线免费观看视频| 亚洲成人黄色在线| 亚洲人免费视频| 久久精品国产一区二区电影| 欧美在线观看www| 亚洲综合一区二区不卡| 98午夜经典影视| 欧美激情xxxx| 国产精品视频久久久| 亚洲国产精品国自产拍av秋霞| 国产精品美女主播| 亚洲成人久久电影| 国产福利精品视频| 亚洲第一天堂无码专区| 亚洲国产精品va在看黑人| 久久久久免费精品国产| 亚洲精品中文字幕有码专区| 亚洲aaa激情| 久久精品视频网站| 91成人性视频| 国产午夜精品全部视频在线播放| 91国产高清在线| 国内成人精品视频| 91精品久久久久久久久不口人| 欧美视频一二三| 国产日韩欧美中文在线播放| 97精品免费视频| 久久天堂av综合合色| 欧美日韩第一视频| 中文字幕在线视频日韩| 一本大道香蕉久在线播放29| 久久艳片www.17c.com| 亚洲国产精品99久久| 亚洲欧美在线x视频| 国产91精品最新在线播放| 久久久免费在线观看| 黄色一区二区在线观看| 国产精品入口免费视频一| 欧美国产精品va在线观看| 国产成人一区二区三区| 精品日本美女福利在线观看| 91亚洲永久免费精品| 久久久免费在线观看| 97视频免费在线看| 亚洲男人第一网站| 欧洲美女免费图片一区| 亚洲午夜精品久久久久久久久久久久| 久久久亚洲国产天美传媒修理工| 久久香蕉频线观| 国产激情999| 亚洲人av在线影院| 亚洲欧美激情视频| 亚洲成人网在线观看| 欧美日韩亚洲一区二区三区| 日韩欧美主播在线| 欧美视频国产精品| 欧美大片在线免费观看| 亚洲国产天堂久久综合| 91美女高潮出水| 国产精选久久久久久| 播播国产欧美激情| 日韩成人在线电影网| 最近免费中文字幕视频2019| 日韩欧美国产黄色| 国产精品久久久久av免费| 欧美视频免费在线观看| 日韩欧美中文字幕在线播放| 一区二区三区在线播放欧美| 国产精品视频999| 亚洲激情国产精品| 日韩在线精品一区| 亚洲精品久久久久久久久| 欧美性理论片在线观看片免费| 久久久久久国产免费| 久久久久久久久电影| 中文字幕在线观看亚洲| 欧美日韩亚洲精品一区二区三区| 色中色综合影院手机版在线观看| 国产噜噜噜噜久久久久久久久| 国产精品爽爽爽| 久久五月天综合| 日韩欧美极品在线观看| 久久久久这里只有精品| 欧美麻豆久久久久久中文| 亚洲欧美成人一区二区在线电影| 尤物yw午夜国产精品视频明星| 国产欧美韩国高清| 欧美精品一本久久男人的天堂| 久久久久国产精品免费| 亚洲人成电影在线观看天堂色| 欧美日韩国产综合新一区| 欧洲日本亚洲国产区| 在线观看日韩www视频免费| 国产精品国产福利国产秒拍| 精品国产区一区二区三区在线观看| 在线亚洲午夜片av大片| 亚洲国产精品久久久| 一区二区三区国产在线观看| 高跟丝袜欧美一区| 亚洲欧美制服丝袜| 日韩电视剧免费观看网站| 欧美日韩中文字幕在线| 欧美激情亚洲自拍| 国产成人精品av在线| 色视频www在线播放国产成人| 美女扒开尿口让男人操亚洲视频网站| 国产成人精品电影| 57pao国产精品一区| 国产精品中文久久久久久久| 日日狠狠久久偷偷四色综合免费| 国产精品美女免费视频| 欧美激情视频在线| 亚洲精品不卡在线| 欧美丰满少妇xxxx| 亚洲午夜国产成人av电影男同| 久久亚洲国产精品成人av秋霞| 精品久久在线播放| 中文字幕日韩av电影| 欧美尤物巨大精品爽| 色一区av在线| 亚洲国产精品小视频| 欧美成人性色生活仑片| 在线电影av不卡网址| 一区二区三区四区在线观看视频| 亚洲福利视频网站| 国产91色在线|免| 91精品久久久久久久久| 国产午夜精品理论片a级探花| 国产亚洲aⅴaaaaaa毛片| 91精品久久久久久久久久| 国模精品视频一区二区三区| 奇米四色中文综合久久| 亚洲一区二区免费在线| 国产成人精品电影| 91精品国产乱码久久久久久久久| 国产午夜精品全部视频播放| 疯狂蹂躏欧美一区二区精品|