更新時(shí)間:2022-11-09 09:35:41 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽1339次
位圖是當(dāng)需要將巨大域的布爾信息映射為緊湊表示時(shí)立即出現(xiàn)在您腦海中的數(shù)據(jù)結(jié)構(gòu)。當(dāng)內(nèi)存空間非常寶貴時(shí),它是一種非常流行的數(shù)據(jù)結(jié)構(gòu)。Redis 作為內(nèi)存數(shù)據(jù)結(jié)構(gòu)服務(wù)器,提供對(duì)位操作操作的支持。
中的數(shù)據(jù)結(jié)構(gòu)。當(dāng)內(nèi)存空間非常寶貴時(shí),它是一種非常流行的數(shù)據(jù)結(jié)構(gòu):操作系統(tǒng)內(nèi)核(內(nèi)存頁(yè)、inode 等)、數(shù)字成像等。
Redis 作為內(nèi)存數(shù)據(jù)結(jié)構(gòu)服務(wù)器,提供對(duì)位操作操作的支持。但是, Redis 中的位圖沒(méi)有特殊的數(shù)據(jù)結(jié)構(gòu) 。相反,基本 Redis 結(jié)構(gòu)支持位級(jí)操作: 字符串。現(xiàn)在,Redis 字符串的最大長(zhǎng)度為 512 MB。因此,Redis 可以映射為 Bitmap 的最大域是 2 32 (512 MB = 2 29 字節(jié) = 2 32 位)。
Redis 中與位相關(guān)的操作有兩種:恒定時(shí)間 (O(1)),例如獲取/設(shè)置特定位的操作,以及基本上對(duì)一組位進(jìn)行操作的 O(N) 操作。在這些情況下,N 是操作需要處理的位長(zhǎng)度。讓我們看一些例子。
# SETBIT key offset value :在'key'的偏移'offset'處存儲(chǔ) 位 值 'value ' 。歐( 1 )
# 返回 存儲(chǔ)在該偏移處的 原始 位 值 。
127.0 . 0.1 : 6379 > 設(shè)置位 k 10 1
(整數(shù)) 0
# GETBIT key offset :在'key'中獲取 'offset'的值 。歐( 1 )
127.0 . 0.1 : 6379 > 獲取比特 k 10
(整數(shù)) 1
127.0 . 0.1 : 6379 > 獲取位 k 11
(整數(shù)) 0
127.0 . 0.1 : 6379 > 獲取位 k 0
(整數(shù)) 0
127.0 . 0.1 : 6379 > 設(shè)置位 k 9 1
(整數(shù)) 0
127.0 . 0.1 : 6379 > 設(shè)置位 k 8 1
(整數(shù)) 0
# 因?yàn)樗匀皇且粋€(gè)通用的String , 所以這里是一個(gè) get 。
127.0 . 0.1 : 6379 > 得到 k
"\x00\xe0"
# "\x00\xe0" -> "0000 0000 111"
#BITCOUNT key [ start end ] :范圍內(nèi)設(shè)置的位數(shù)。_ _ 歐( ? )
# 重要:開(kāi)始 和 結(jié)束 是 字節(jié) 而不是 位
127.0 . 0.1 : 6379 > 比特 數(shù) k
(整數(shù)) 3
127.0 . 0.1 : 6379 > 設(shè)置 m “喵”
好的
# 喵 -> 01101101 01100101 01101111 01110111
127.0 . 0.1 : 6379 > 位數(shù) m
(整數(shù)) 21
# BITPOS key bit [ start ] [ end ] : key in range中1或0的第 一個(gè)位置 。歐( ? )
127.0 . 0.1 : 6379 > 設(shè)置我的密鑰“\ xff \xf0\x00”
好的
127.0 . 0.1 : 6379 > BITPOS mykey 0
(整數(shù)) 12
除了對(duì)鍵本身起作用的運(yùn)算符外,BITOP 運(yùn)算符還用于多個(gè)鍵之間的按位邏輯運(yùn)算。
# BITOP 操作 destkey key [ key ...]. 歐( ? )
# 運(yùn)算 可以 是 AND , OR , XOR 和 NOT
127.0 . 0.1 : 6379 > 設(shè)置 一個(gè) “\xff\xff”
好的
127.0 . 0.1 : 6379 > bitop 不是 nota _
(整數(shù)) 2
127.0 . 0.1 : 6379 > 得到 通知
"\x00\x00"
127.0 . 0.1 : 6379 > 設(shè)置 b "\x0f\x0f"
好的
127.0 . 0.1 : 6379 > 設(shè)置 c "\xf0\xf0"
好的
127.0 . 0.1 : 6379 > BITOP 或 orbc b c
(整數(shù)) 2
127.0 . 0.1 : 6379 > 獲得 orbc
"\xff\xff"
127.0 . 0.1 : 6379 > BITOP AND andbc b c
(整數(shù)) 2
127.0 . 0.1 : 6379 > 得到 andbc
"\x00\x00"
127.0 . 0.1 : 6379 > BITOP XOR xorbc b c
(整數(shù)) 2
127.0 . 0.1 : 6379 > 得到 xorbc
"\xff\xff"
由于位圖操作沒(méi)有自己的數(shù)據(jù)結(jié)構(gòu),因此沒(méi)有特殊的數(shù)據(jù)結(jié)構(gòu)可以描述。Redis 字符串本身是作為二進(jìn)制安全字符串實(shí)現(xiàn)的。Redis 字符串?dāng)?shù)據(jù)結(jié)構(gòu)內(nèi)部稱為簡(jiǎn)單動(dòng)態(tài)字符串(SDS)。它本質(zhì)上是一個(gè)帶有一些額外簿記信息的原生 char []。
位圖函數(shù)的實(shí)現(xiàn)在文件 bitops.c中。
PS 鑒于位操作算法對(duì)關(guān)鍵操作系統(tǒng)和圖形功能的重要性,大多數(shù)架構(gòu)都為此類操作提供了特殊指令。閱讀各種有趣的計(jì)算機(jī)算術(shù)算法的好地方是永恒的經(jīng)典 Hacker's Delight。
這個(gè) 流行的 GetSpool 博客 是使用位圖對(duì)大型數(shù)據(jù)集進(jìn)行實(shí)時(shí)分析的一個(gè)很好的例子。它也是位圖經(jīng)典用例的一個(gè)示例:將極大域的布爾信息存儲(chǔ)到(相對(duì))較小的空間中,同時(shí)保持良好的性能。
尺寸通常是非常大的位圖的一個(gè)問(wèn)題,因?yàn)閷?duì)其最有用的操作是 O(N)。為了避免使用大鍵,Redis 文檔 建議 將大鍵拆分為多個(gè)較小的鍵。在密鑰變大之前,BITCOUNT 性能仍然可以接受。此時(shí),建議是拆分鍵或使用范圍參數(shù)進(jìn)行增量查詢。 處理緩慢的 BITOP 操作的 建議是在從站上運(yùn)行它。因此,一般來(lái)說(shuō),處理中等大小的密鑰并通過(guò)將密鑰拆分為多個(gè)密鑰來(lái)規(guī)劃未來(lái)的潛在增長(zhǎng)是有意義的。
Redis Sets 和位圖操作提供的功能本質(zhì)是相似的。所以經(jīng)常混淆這兩種方法中的哪一種更好。好吧,這實(shí)際上取決于用例的確切性質(zhì)。顯然,這個(gè)討論只對(duì)集合和位圖都可以實(shí)現(xiàn)的那種操作有效。
Redis Sets 通常是高效且可擴(kuò)展的,并且應(yīng)該是首選的數(shù)據(jù)結(jié)構(gòu),直到它的大小變得難以為繼。Redis Set 也更易于管理,編程和調(diào)試適用于大多數(shù)應(yīng)用程序。不應(yīng)低估 Set 的易用性:操作位圖的代碼通常難以閱讀、理解、調(diào)試和維護(hù)。即使域非常大,集合仍然可能是合適的。例如,如果一個(gè)應(yīng)用程序旨在跟蹤對(duì)熱門(mén)電子商務(wù)網(wǎng)站的每日訪問(wèn)量,那么結(jié)果可能仍然很適合一組,因?yàn)橥ǔV挥?5-10% 的整個(gè)用戶群會(huì)每天訪問(wèn)該網(wǎng)站。對(duì)于預(yù)計(jì) 60% 的整個(gè)用戶群每天登錄的網(wǎng)站來(lái)說(shuō),這顯然會(huì)發(fā)生變化。然后,考慮到對(duì)大量鍵的邏輯按位操作的大小和性能,位圖變得更加相關(guān)。Redis Set 還具有不必將 ID 映射到位偏移量的明顯優(yōu)勢(shì)。同樣,如果您的值來(lái)自大于 2 的域32 那么Redis Sets必須比找出機(jī)制來(lái)分割位圖的域更容易使用。
這是一個(gè)編造的(但足夠真實(shí)!)示例,用于可能應(yīng)用 Redis 位圖操作的地方。假設(shè)您正在運(yùn)行一個(gè)非常受歡迎的在線 MOOC ,成千上萬(wàn)的學(xué)生已經(jīng)注冊(cè)了該 MOOC。促進(jìn)課程的學(xué)術(shù)團(tuán)隊(duì)想要一個(gè)儀表板,他們可以在其中查看學(xué)生進(jìn)度的實(shí)時(shí)狀態(tài)以及注冊(cè)學(xué)生的一般背景。您決定通過(guò) Redis 位圖操作來(lái)實(shí)現(xiàn)這一點(diǎn)。這是一個(gè)逐步的方法。
創(chuàng)建一個(gè)計(jì)劃以在學(xué)生 ID 和位圖偏移之間進(jìn)行映射。它可以像 ID 作為位圖中的偏移量一樣簡(jiǎn)單。
課程開(kāi)始后,創(chuàng)建和填充各種與人口統(tǒng)計(jì)相關(guān)的位圖。例如,在同一所大學(xué)注冊(cè)其他 MOOC 的學(xué)生、教育水平、性別等。
現(xiàn)在隨著課程的進(jìn)行,您可以創(chuàng)建新的位圖來(lái)記錄課程進(jìn)度。例如,完成第一周所有講座的學(xué)生,完成第一周所有作業(yè)的學(xué)生等。
現(xiàn)在,基于這些鍵創(chuàng)建實(shí)時(shí)分析將是一個(gè)非常簡(jiǎn)單的練習(xí),并且可以在拖放 UI 上完成。例如
一位教授想看看有多少學(xué)生觀看了第一周(A)的講座,但沒(méi)有完成第一周(B)的作業(yè):操作員:BITOP。操作:A AND(非 B)。
完成第 1 周 (A)、第 2 周 (B)、第 3 周 (C) 和第 4 周 (D) 的所有作業(yè)的學(xué)生:操作員:BITOP。操作 A AND B AND C AND D. 說(shuō),這些是通過(guò)課程的人。
通過(guò)課程的所有男學(xué)生(M)(如上計(jì)算,比如說(shuō),P):操作員:BITOP。操作:M AND P。
通過(guò)課程的學(xué)生人數(shù):BITCOUNT P.
類似地,可以將任意數(shù)量的有趣群組設(shè)置為位圖,并在其上運(yùn)行此類排列。
以上就是關(guān)于“Redis數(shù)據(jù)結(jié)構(gòu):位圖”介紹,如果大家想了解更多相關(guān)知識(shí),不妨來(lái)關(guān)注一下本站的Redis教程,里面還有更豐富的知識(shí)等著大家去學(xué)習(xí),希望對(duì)大家能夠有所幫助。
相關(guān)閱讀
Java實(shí)驗(yàn)班
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
Java就業(yè)班
有基礎(chǔ) 直達(dá)就業(yè)
Java夜校直播班
業(yè)余時(shí)間 高薪轉(zhuǎn)行
Java在職加薪班
工作1~3年,加薪神器
Java架構(gòu)師班
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)