一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數據庫技術|

服務器之家 - 數據庫 - Redis - 聊聊Redis二進制數組Bitmap

聊聊Redis二進制數組Bitmap

2021-10-10 22:43Leon0204 Redis

這篇文章主要介紹了Redis二進制數組Bitmap,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

好久沒有更新了,之前公司在做 關注/粉絲 這塊兒緩存的時候,我選擇的就是 Bitmap ,那時是我第一次見識到這種數據數組形式,用到的有 SETBIT , GETBIT , BITCOUNT ,命令如何使用就不說了,今天來仔細看看這三個命令的實現和原理。

選用 bitmap 的考量:

位數組的實現

關注關系需求中 關注對象 和 被關注人 都是 0-幾千萬 的數據對象,存儲這種對應關系時,采用bitmap 這種位數組,明顯要比 uid 的 set 方式要節省存儲空間,redis 的 內存 是很寶貴的,這值得作為考量的地方。

位數組大致可表示為:0101010000100000....0100 這樣的二進制串, 在 Redis 的 SDS字符串 一文中可以看到 Redis 中的字符串對象實現,SDS數據結構是二進制安全的,所以 Redis 可以使用字符串來表示 位數組 。 所以根據上面說的,位數組是以字符串的形式:buf[0]|buf[1]...這樣一個一個字節存放的。

SETBIT 和 GETBIT

GETBIT 的實現:

?
1
2
3
4
5
6
7
# 返回 位數組 bitarray 在 offset 偏移量上的二進制位(byte*8+bit)的值
getbit <bitarray> <offset>
# 字節
byte = offset / 8 
# 位
bit = (offset mod 8) + 1
# 可以看到 O(1)

SETBIT 的實現:

?
1
2
3
4
5
6
7
8
9
10
# 將 位數組 bitarray 在offset 偏移量上的二進制位的值設置為 value
setbit <bitarray> <offset> <value>
# 計算保存二進制位需要多少 字節
len = [offset / 8] + 1
# 魷魚 ? 二進制位數組使用的數據結構是 sds ,而 sds 記錄長度的是len ,正常進行擴展,同空間預分配 ,擴展位為`00000`
# 字節
byte = offset / 8 
# 位
bit = (offset mod 8) + 1
# 記錄 (byte*8+bit) 上 oldvalue ,再賦予新值,返回 oldvalue

Bitcount 的實現

BITCOUNT 統計給定位數組中,值為1 的數量,也就是統計漢明重量(見 Leetcode 191、338),其實是一個老問題,看看幾種算法,和 redis 的做法。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#1. 粗暴遍歷 O(n)
 
class Solution(object):
    def hammingWeight(self, n):
        rst = 0
        mask = 1
        for i in range(32):
            if n & mask :
                rst += 1
            mask = mask << 1
        return  rst
        
#2. 查表法
# 查表法原理在于建立N個位數組,如果是8位,即減少查詢次數/8 ,建表越大,則查詢次數越少
# 空間換時間的典型操作,不禁讓我想起了 計數排序O(n+k)
# 內存考慮:這里可以算一下 8位的查表耗費的內存百字節,16位查表為百Kb,32位為十多個G,實際中,服務器只能接受16位
# CPU考慮:表長越大,miss 率越大。而 max 為16 也不能解決大數組的查表效率問題
# 這種算法 O(n/m) S(m) m<=16
 
#3.variable-precision SWAR 算法 O(1)
 
#4.Redis
# redis 未處理的二進制數 >= 128,使用variable-precision SWAR
# redis 未處理的二進制數 < 128,使用 查表法

Redis-高性能bitmap

實時指標

Redis bitmap可用于快速、簡單的實現實時指標。

傳統情況下,由批量job生成指標數據。但是redis的bitmap支持實時指標計算,而且具有極高的空間利用率。例如1.28億用戶,實時統計日UV,僅僅占用16MB內存空間,在mbp上耗時50ms。

bitset

可視為由0和1組成的數組。在bitset中的每個bit可為0或1,使用offset表示bit在數組的位置。支持多個bitset間進行位操作,如與或非等。

群體統計

bitset的群體統計表示bitset中數據為1的bit數量。使用bitset做群體統計是非常高效的。如具有十億bit的bitset,其90%空間已設置數據,在mbp上進行群體統計僅耗時幾十或幾百ms。

redis bitmap

bitmap是二進制數據,可通過set key offset val指令設置具體offset位置bit的數據,且時間復雜度為O(1)。

日活用戶

針對關注點(某個頁面或某個操作),統計活躍用戶數量。

key規則:關注點名稱+日時間戳

val:創建bitmap,寬度為當前用戶數量,每個用戶的id作為offset,這個用戶ID是記錄ID,不可能是由特定規則生成的userID。

當用戶訪問關注點時,針對具體bitset,將用戶IDoffset位置數據設置為1。之后對該bitset進行群體統計,即為關注點的日活用戶量。

采取關注點名稱+時間戳的方式,可以存儲不同時間維度的活躍用戶。

如每小時播放音樂的用戶量,key定義為play_yyyyMMddhh;每天播放音樂的用戶量,key定義為play_yyyyMMdd。

當需要統計較大時間范圍的用戶量時,可以先對多個bitset求并集,然后再群體統計,如統計一周、一個月的用戶量。

性能對比

1.28億用戶,使用bitset記錄日活,使用日活并集統計7日 15日日活。
PERIOD TIME (MS)
Daily 50.2
Weekly 392.0
Monthly 1624.8

特性分析

周維度訪問關注點且綁定手機號的唯一用戶,采用綁定手機號用戶bitset 交集 周維度訪問關注點的用戶bitset

最近n天唯一用戶量的滾動統計,對最近n天每天的日活用戶bitset求并集

涉及的指令

群體統計使用bitcount key

交集并集使用bitop and/or dest key1 keyn

對用戶IDoffset設置數據使用setbit key offset 1

?
1
java bitset.cardinality()/and(bitset)/or(bitset)

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://siwei.blog.csdn.net/article/details/88698399

延伸 · 閱讀

精彩推薦
  • Redis詳解Redis復制原理

    詳解Redis復制原理

    與大多數db一樣,Redis也提供了復制機制,以滿足故障恢復和負載均衡等需求。復制也是Redis高可用的基礎,哨兵和集群都是建立在復制基礎上實現高可用的...

    李留廣10222021-08-09
  • Redisredis 交集、并集、差集的具體使用

    redis 交集、并集、差集的具體使用

    這篇文章主要介紹了redis 交集、并集、差集的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友...

    xiaojin21cen10152021-07-27
  • RedisRedis 事務知識點相關總結

    Redis 事務知識點相關總結

    這篇文章主要介紹了Redis 事務相關總結,幫助大家更好的理解和學習使用Redis,感興趣的朋友可以了解下...

    AsiaYe8232021-07-28
  • Redisredis實現排行榜功能

    redis實現排行榜功能

    排行榜在很多地方都能使用到,redis的zset可以很方便地用來實現排行榜功能,本文就來簡單的介紹一下如何使用,具有一定的參考價值,感興趣的小伙伴們...

    乘月歸5022021-08-05
  • Redisredis中如何使用lua腳本讓你的靈活性提高5個逼格詳解

    redis中如何使用lua腳本讓你的靈活性提高5個逼格詳解

    這篇文章主要給大家介紹了關于redis中如何使用lua腳本讓你的靈活性提高5個逼格的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具...

    一線碼農5812019-11-18
  • RedisRedis全量復制與部分復制示例詳解

    Redis全量復制與部分復制示例詳解

    這篇文章主要給大家介紹了關于Redis全量復制與部分復制的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Redis爬蟲具有一定的參考學習...

    豆子先生5052019-11-27
  • RedisRedis的配置、啟動、操作和關閉方法

    Redis的配置、啟動、操作和關閉方法

    今天小編就為大家分享一篇Redis的配置、啟動、操作和關閉方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    大道化簡5312019-11-14
  • RedisRedis如何實現數據庫讀寫分離詳解

    Redis如何實現數據庫讀寫分離詳解

    Redis的主從架構,能幫助我們實現讀多,寫少的情況,下面這篇文章主要給大家介紹了關于Redis如何實現數據庫讀寫分離的相關資料,文中通過示例代碼介紹...

    羅兵漂流記6092019-11-11
主站蜘蛛池模板: 大象视频污 | 国产精品久久国产精品99盘 | 亚洲国产剧情中文视频在线 | 91亚洲一区二区在线观看不卡 | 母爱成瘾在线观看 | 国内免费高清视频在线观看 | 国产一卡二卡3卡4卡更新 | 91精品国产高清久久久久久io | 97色资源 | 天堂网站天堂小说 | 黄www片 | 教室里的激情电影 | 高清视频大片免费观看 | 日本精品一二三区 | 国产精品视频久 | 国产精品福利一区二区亚瑟 | 千金在线观看 | 日本男男漫画 | 星空传媒在线视频 | 日本高清视频网站www | 嫩草影院永久一二三入口 | 欧美亚洲国产综合在线 | 玩乳h文奶水和尚 | 欧美一区二区三区精品国产 | 免费深夜福利 | 波多野结衣之双方调教在线观看 | 国产短视频精品一区二区三区 | 精品女同同性视频很黄很色 | 国产成人精品免费2021 | 青苹果乐园影院免费观看完整版 | 成年人视频在线免费看 | 亚洲日本中文字幕天天更新 | 天天爱天天做天天爽天天躁 | 国产视频一区 | 99视频精品免费99在线 | 热99这里只有精品 | 久久三级视频 | 成人国产精品视频频 | 国产一级片视频 | 成年人免费在线看的惊悚动作片 | 亚洲精品久久中文字幕 |