精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

我畫了19張圖,幫你徹底搞懂Redis

存儲(chǔ) 存儲(chǔ)軟件 開發(fā)工具 Redis
又到了金三銀四跳槽季,好多同學(xué)已經(jīng)開始行動(dòng)了。今天我來助力一把,送出這套 Redis 面試題,助力大家通關(guān)。

 又到了金三銀四跳槽季,好多同學(xué)已經(jīng)開始行動(dòng)了。今天我來助力一把,送出這套 Redis 面試題,助力大家通關(guān)。

[[389121]]

 

圖片來自 Pexels

Redis 為什么響應(yīng)快

①數(shù)據(jù)保存在內(nèi)存中

Redis 數(shù)據(jù)保存在內(nèi)存中,讀寫操作只要訪問內(nèi)存,不需要磁盤 IO。

②底層數(shù)據(jù)結(jié)構(gòu)

如下:

  • Redis 的數(shù)據(jù)以 key:value 的格式存儲(chǔ)在散列表中,時(shí)間復(fù)雜度 o(1)。
  • Redis 為 value 定義了豐富的數(shù)據(jù)結(jié)構(gòu),包括動(dòng)態(tài)字符串、雙向鏈表、壓縮列表、hash、跳表和整數(shù)數(shù)組,可以根據(jù) value 的特性選擇選擇最高效的數(shù)據(jù)結(jié)構(gòu)。

③單線程模型

Redis 的網(wǎng)絡(luò) IO 和數(shù)據(jù)讀寫使用單線程模型,可以綁定 CPU,這避免了線程上下文切換帶來的開銷。

注意:Redis 6.0 對網(wǎng)絡(luò)請求引入了多線程模型,讀寫操作還是用單線程。

Redis 多線程網(wǎng)絡(luò)模型見下圖:

 

④IO 多路復(fù)用

Redis 采用 Epoll 網(wǎng)絡(luò)模型,如下圖:

 

內(nèi)核會(huì)一直監(jiān)聽新的 socket 連接事件的和已建立 socket 連接的讀寫事件,把監(jiān)聽到的事件放到事件隊(duì)列,Redis 使用單線程不停的處理這個(gè)事件隊(duì)列。這避免了阻塞等待連接和讀寫事件到來。

這些事件綁定了回調(diào)函數(shù),會(huì)調(diào)用 Redis 的處理函數(shù)進(jìn)行處理。

Redis 底層數(shù)據(jù)結(jié)構(gòu)

Redis 有 5 種數(shù)據(jù)類型,包括:字符串、列表、集合、有序集合和字典。

Redis 底層的數(shù)據(jù)結(jié)構(gòu)有 6 種,包括:動(dòng)態(tài)字符串、雙向鏈表、壓縮列表(ziplist)、hash 表、跳表(skip list)和整數(shù)數(shù)組。

Redis 數(shù)據(jù)類型和底層數(shù)據(jù)結(jié)構(gòu)有如下對應(yīng)關(guān)系:

 

①字符串類型

底層數(shù)據(jù)結(jié)構(gòu)是動(dòng)態(tài)字符串。

②列表

如果同時(shí)滿足下面條件,就使用壓縮列表,否則使用雙向鏈表:

  • 列表中單個(gè)元素小于 64 字節(jié)
  • 列表中元素個(gè)數(shù)少于 512

壓縮列表在內(nèi)存中是一塊兒連續(xù)的內(nèi)存空間,結(jié)構(gòu)如下:

 

壓縮列表查找時(shí)間復(fù)雜度是 o(n)。

③集合

如果同時(shí)滿足下面條件,就使用有序整數(shù)數(shù)組,否則使用 hash 表:

  • 集合中元素都是整數(shù)類型
  • 集合中元素個(gè)數(shù)不超過 512 個(gè)

④有序集合

如果同時(shí)滿足下面 2 個(gè)條件,就使用壓縮列表,否則使用跳表:

  • 集合中元素都小于 64 字節(jié)
  • 集合中元素個(gè)數(shù)小于 128 個(gè)

注意:有序集合還有一個(gè) HASH 表用于保存集合中元素的分?jǐn)?shù),做 ZSCORE 操作時(shí),查詢的就是這個(gè) HASH 表,所以效率很高。

跳表的結(jié)構(gòu)如下:

 

如果不加索引,查找 10 這個(gè)數(shù)字需要查詢 10 次,使用了二級索引,查找 10 這個(gè)數(shù)字需要 5 次,而使用一級索引,需要查詢 3 次。

跳表的每一層都是一個(gè)有序鏈表,最下面一層保存了全部數(shù)據(jù)。跳表插入、刪除、查詢的時(shí)間復(fù)雜度是 o(logN)。跳表需要存儲(chǔ)額外的索引節(jié)點(diǎn),會(huì)增加額外的空間開銷。

⑤字典

如果同時(shí)滿足下面 2 個(gè)條件,就使用壓縮列表,否則使用 hash 表:

  • 字典中每個(gè) entry 的 key/value 都小于 64 字節(jié)
  • 字典中元素個(gè)數(shù)小于 512 個(gè)

Redis 緩存淘汰策略

Redis 總共有 8 種淘汰策略,如下圖:

 

volatile-lfu 和 allkeys-lfu 策略是 4.0 版本新增的:

  • lru:是按照數(shù)據(jù)的最近最少訪問原則來淘汰數(shù)據(jù),可能存在的問題是如果大批量冷數(shù)據(jù)最近被訪問了一次,就會(huì)占用大量內(nèi)存空間,如果緩存滿了,部分熱數(shù)據(jù)就會(huì)被淘汰掉。
  • lfu:是按照數(shù)據(jù)的最小訪問頻率訪問次數(shù)原則來淘汰數(shù)據(jù),如果兩個(gè)數(shù)據(jù)的訪問次數(shù)相同,則把訪問時(shí)間較早的數(shù)據(jù)淘汰。

Redis 數(shù)據(jù)持久化

Redis 持久化的方式有 2 種,一種是寫后日志(AOF),一種是內(nèi)存快照(RDB)。

①AOF 日志

AOF 日志記錄了每一條收到的命令,Redis 故障宕機(jī)恢復(fù)時(shí),可以加載 AOF 日志中的命令進(jìn)行重放來進(jìn)行故障恢復(fù)。

AOF 有 3 種同步策略,如下圖:

 

如果不是對丟失數(shù)據(jù)特別敏感的業(yè)務(wù),推薦使用 everysec,對主線程的阻塞少,故障后丟失數(shù)據(jù)只有 1s。

②RDB 快照

RDB 快照是一個(gè)內(nèi)存快照,記錄了 Redis 某一時(shí)刻的全部數(shù)據(jù)。

③混合日志

從 Redis 4.0 開始,AOF 文件也可以保存 RDB 快照,AOF 重寫的時(shí)候 Redis 會(huì)把 AOF 文件內(nèi)容清空,先記錄一份 RDB 快照,這份數(shù)據(jù)以"REDIS"開頭。

記錄 RDB 內(nèi)容后,AOF 文件會(huì)接著記錄 AOF 命令。故障恢復(fù)時(shí),先加載 AOF 文件中 RDB 快照,然后回放 AOF 文件中后面的命令。

④主從同步

Redis 主從同步時(shí),主節(jié)點(diǎn)會(huì)先生成一份 RDB 快照發(fā)送給從節(jié)點(diǎn),把快照之后的命令寫入主從同步緩存區(qū)(replication buffer),從節(jié)點(diǎn)把 RDB 文件加載完成后,主節(jié)點(diǎn)把緩存區(qū)命令發(fā)送給從節(jié)點(diǎn)。

⑤AOF 重寫

AOF 日志是用記錄命令的方式追加的,這樣可能存在對同一個(gè) key 的多條命令,這些命令是可以合并成 1 條的。比如對同一個(gè) key 的多個(gè) set 操作日志,可以合成一條。

⑥阻塞點(diǎn)

AOF 重寫和 RDB 快照執(zhí)行的過程中,Redis 都會(huì) Fork 一個(gè)子進(jìn)程來執(zhí)行操作,子進(jìn)程執(zhí)行過程中是不是阻塞主線程的。

但是要注意 2 點(diǎn):

  • Fork 子進(jìn)程的過程中,Redis 主線程會(huì)拷貝一份內(nèi)存頁表(記錄了虛擬內(nèi)存和物理內(nèi)存的映射關(guān)系)給子進(jìn)程,這個(gè)過程是阻塞的,Redis 主線程內(nèi)存越大,阻塞時(shí)間越長。
  • 子進(jìn)程和 Redis 主線程共用一塊兒物理內(nèi)存,如果新的請求到來,必須使用 copy on write 的方式,拷貝要修改的數(shù)據(jù)頁到新的內(nèi)存空間進(jìn)行修改。如下圖:

 

注意:如果開啟了內(nèi)存大頁,每次拷貝都需要分配 2MB 的內(nèi)存。

Redis 高可用

下圖是一個(gè)“一主二從三哨兵”的架構(gòu)圖:

 

從圖我們可以看到哨兵之間、哨兵和主從節(jié)點(diǎn)之間、哨兵和客戶端之間都建立了連接。

如果主節(jié)點(diǎn)掛了,哨兵集群需要完成主從切換,如下圖:

 

下面我們依次來聊一下這 4 個(gè)步驟。

①判斷主節(jié)點(diǎn)下線

當(dāng)一個(gè)哨兵監(jiān)控到主節(jié)點(diǎn)下線時(shí),就會(huì)給其他哨兵發(fā)送確認(rèn)命令,其他命令會(huì)根據(jù)自己的判斷回復(fù)"Y"或"N"。

如果有 n/2+1 以上數(shù)量的哨兵都認(rèn)為主節(jié)點(diǎn)下線了,才會(huì)判定主節(jié)點(diǎn)下線。這里的n是哨兵集群的數(shù)量。

n/2+1 這個(gè)參數(shù)由 quorum 參數(shù)配置,比如有 5 個(gè)哨兵,這里一般配置成 3。也可以配置成其他值。

②選舉新主節(jié)點(diǎn)

主節(jié)點(diǎn)被判定下線后,哨兵集群會(huì)重新選擇新的主節(jié)點(diǎn)。

淘汰不穩(wěn)定從節(jié)點(diǎn):根據(jù)配置參數(shù) down-after-milliseconds * 10 來淘汰。

down-after-milliseconds 表示主從節(jié)點(diǎn)斷開時(shí)間,10 表示次數(shù),如果從節(jié)點(diǎn)跟主節(jié)點(diǎn)斷開時(shí)間超過 down-after-milliseconds 的次數(shù)達(dá)到了 10 次以上,從節(jié)點(diǎn)就被淘汰了。

slave-priority 參數(shù):配置了從節(jié)點(diǎn)的優(yōu)先級,選擇從節(jié)點(diǎn)時(shí)哨兵會(huì)優(yōu)先選擇優(yōu)先級高的從節(jié)點(diǎn)。

復(fù)制進(jìn)度:Redis 有一個(gè)記錄主從增量復(fù)制的緩存區(qū)叫 repl_backlog_buffer。

這是一個(gè)環(huán)形結(jié)構(gòu)的緩沖區(qū),如下圖:

 

主節(jié)點(diǎn)有一個(gè)寫偏移量 master_repl_offset,從節(jié)點(diǎn)也有一個(gè)偏移量 slave_repl_offset。

優(yōu)先選擇 slave_repl_offset 最接近 master_repl_offset 的從節(jié)點(diǎn)作為新的主節(jié)點(diǎn)。

所以,上圖中偏移量為 114 的從節(jié)點(diǎn)優(yōu)先被選為新的主節(jié)點(diǎn)。

ID 編號:優(yōu)先級和參數(shù)都一樣的情況下,ID 編號小的從節(jié)點(diǎn)優(yōu)先被選為新主節(jié)點(diǎn)。

③選舉哨兵 Leader

第一個(gè)判斷主節(jié)點(diǎn)下線的哨兵節(jié)點(diǎn)收到其他節(jié)點(diǎn)的回復(fù)并確定主節(jié)點(diǎn)下線后,就會(huì)給其他哨兵發(fā)送命令申請成為哨兵 Leader。

成為 Leader 的條件如下:

收到贊成票必須大于等 quorum 值

必須拿到半數(shù)以上的贊成票

如果集群配置了 5 個(gè)哨兵,quorum 的值設(shè)置為 3,其中一個(gè)哨兵節(jié)點(diǎn)掛了,很有可能會(huì)判斷到主節(jié)點(diǎn)下線,但是因?yàn)檫x舉不出哨兵 Leader 而不能切換。

如果集群有 2 個(gè)哨兵,其中一個(gè)掛了,那必定選不出哨兵 Leader。

下面的圖展示了哨兵一成功當(dāng)選 Leader 的過程:

 

④主節(jié)點(diǎn)切換

選出新主節(jié)點(diǎn)和哨兵 Leader 后,哨兵 Leader 會(huì)執(zhí)行主從切換的操作。

完成后會(huì)做一些事件通知:

  • 通知其他哨兵新主節(jié)點(diǎn)地址
  • 通知所有從節(jié)點(diǎn)新的主節(jié)點(diǎn)地址,從節(jié)點(diǎn)收到后向新主節(jié)點(diǎn)請求主從同步
  • 通知客戶端連接新主節(jié)點(diǎn)

⑤主從切換過程中請求處理

如果客戶端的讀請求會(huì)發(fā)送到從節(jié)點(diǎn),可以正常處理。在客戶端收到新主節(jié)點(diǎn)地址通知前寫請求會(huì)失敗??蛻舳丝梢圆扇∫恍?yīng)急措施應(yīng)對主節(jié)點(diǎn)下線,比如緩存寫請求。

為了能夠及時(shí)獲取到新主節(jié)點(diǎn)信息,客戶端可以訂閱哨兵的主節(jié)點(diǎn)下線事件和新主節(jié)點(diǎn)變更事件。

Redis 為什么變慢了

Redis 變慢了的原因有很多,總結(jié)一下有 11 個(gè),見下圖:

 

從圖中看出,Redis 變慢原因主要有兩類:阻塞主線程和操作系統(tǒng)限制。

①主線程阻塞

AOF 重寫和 RDB 快照:前面已經(jīng)講過了,Redis 在 AOF 重寫時(shí),主線程會(huì) Fork 出一個(gè) bgrewriteaof 子進(jìn)程。Redis 進(jìn)行 RDB 快照時(shí)主線程會(huì) Fork 出一個(gè) bgsave 子進(jìn)程。

這兩個(gè)操作表面上看不阻塞主線程,但 Fork 子進(jìn)程的這個(gè)過程是在主線程完成的。

Fork 子進(jìn)程時(shí) Redis 需要拷貝內(nèi)存頁表,如果 Redis 實(shí)例很大,這個(gè)拷貝會(huì)耗費(fèi)大量的 CPU 資源,阻塞主線程的時(shí)間也會(huì)變長。

內(nèi)存大頁:Redis 默認(rèn)支持內(nèi)存大頁是 2MB,使用內(nèi)存大頁,一定程度上可以減少 Redis 的內(nèi)存分配次數(shù),但是對數(shù)據(jù)持久化會(huì)有一定影響。

Redis 在 AOF 重寫和 RDB 快照過程中,如果主線程收到新的寫請求,就需要 CopyOnWrite。

使用了內(nèi)存大頁,即使 Redis 只修改其中一個(gè)大小是 1kb 的 key,也需要拷貝一整頁的數(shù)據(jù),即 2MB。在寫入量較多時(shí),大量拷貝就會(huì)導(dǎo)致 Redis 性能下降。

命令復(fù)雜度高:執(zhí)行復(fù)雜度高的命令是造成 Redis 阻塞的常見原因。比如對一個(gè) set 或者 list 數(shù)據(jù)類型執(zhí)行 SORT 操作,復(fù)雜度是 O(N+M*log(M))。

bigkey 操作:如果一個(gè) key 的 value 非常大,創(chuàng)建的時(shí)候分配內(nèi)存會(huì)很耗時(shí),刪除的時(shí)候釋放內(nèi)存也很耗時(shí)。

Redis 4.0 以后引入了 layfree 機(jī)制,可以使用子進(jìn)程異步刪除,從而不影響主線程執(zhí)行。用 UNLINK 命令替代 DEL 命令,就可以使用子進(jìn)程異步刪除。

Redis 6.0 增加了配置項(xiàng) lazyfree-lazy-user-del,配置成 yes 后,del 命令也可以用子進(jìn)程異步刪除。

如果 lazyfree-lazy-user-del 不設(shè)置為 yes,那 Redis 是否采用異步刪除,是要看刪除的時(shí)機(jī)的。

對于 String 類型和底層采用整數(shù)數(shù)組和壓縮列表的數(shù)據(jù)類型,Redis 是不會(huì)采用異步刪除的。

從節(jié)點(diǎn)全量同步:從節(jié)點(diǎn)全量同步過程中,需要先清除內(nèi)存中的數(shù)據(jù),然后再加載 RDB 文件,這個(gè)過程中是阻塞的,如果有讀請求到來,只能等到加載 RDB 文件完成后才能處理請求,所以響應(yīng)會(huì)很慢。

另外,如果 Redis 實(shí)例很大,也會(huì)造成 RDB 文件太大,從庫加載時(shí)間長。所以盡量保持 Redis 實(shí)例不要太大,比如單個(gè)實(shí)例限制 4G,如果超出就采用切片集群。

AOF 同步寫盤:appendfsync 策略有 3 種:always、everysec、no,如果采用 always,每個(gè)命令都會(huì)同步寫盤,這個(gè)過程是阻塞的,等寫盤成功后才能處理下一條命令。

除非是嚴(yán)格不能丟數(shù)據(jù)的場景,否則盡量不要選擇 always 策略,推薦盡量選擇 everysec 策略,如果對丟失數(shù)據(jù)不敏感,可以采用 no。

內(nèi)存達(dá)到 maxmemory:需要使用淘汰策略來淘汰部分 key。即使采用 lazyfree 異步刪除,選擇 key 的過程也是阻塞的。

可以選擇較快的淘汰策略,比如用隨機(jī)淘汰來替換 LRU 和 LFU 算法淘汰。也可以擴(kuò)大切片數(shù)量來減輕淘汰 key 的時(shí)間消耗。

②操作系統(tǒng)限制

使用了 swap:使用 swap 的原因是操作系統(tǒng)不能給 Redis 分配足夠大的內(nèi)存,如果操作其他開啟了 swap,內(nèi)存數(shù)據(jù)就需要不停地跟 swap 換入和換出,對性能影響非常大。

操作系統(tǒng)沒有能力分配內(nèi)存的原因也可能是其他進(jìn)程使用了大量的內(nèi)存。

網(wǎng)絡(luò)問題:如果網(wǎng)卡負(fù)載很大,對 Redis 性能影響會(huì)很大。這一方面有可能 Redis 的訪問量確實(shí)很高,另一方面也可能是有其他流量大的程序占用了帶寬。

這個(gè)最好從運(yùn)維層面進(jìn)行監(jiān)控。

線程上下文切換:Redis 雖然是單線程的,但是在多核 CPU 的情況下,也可能會(huì)發(fā)生上下文切換。

如果主線程從一個(gè)物理核切換到了另一個(gè)物理核,那就不能使用 CPU 高效的一級緩存和二級緩存了。

如下圖所示:

 

為防止這種情況,可以把 Redis 綁定到一個(gè) CPU 物理核。

磁盤性能低:對于 AOF 同步寫盤的使用場景,如果磁盤性能低,也會(huì)影響 Redis 的響應(yīng)??梢詢?yōu)先采用性能更好的 SSD 硬盤。

設(shè)計(jì)排行榜功能

Redis 的 zset 類型保存了分?jǐn)?shù)值,可以方便的實(shí)現(xiàn)排行榜的功能。

比如要統(tǒng)計(jì) 10 篇文章的排行榜,可以先建立一個(gè)存放 10 篇文章的 zset,每當(dāng)有讀者閱讀一篇文章時(shí),就用 ZINCRBY 命令給這篇文章的分?jǐn)?shù)加 1,最后可以用 range 命令統(tǒng)計(jì)排行榜前幾位的文章。

Redis 實(shí)現(xiàn)分布式鎖

①Redis 單節(jié)點(diǎn)的分布式鎖

如下圖,一個(gè)服務(wù)部署了 2 個(gè)客戶端,獲取分布式鎖時(shí)一個(gè)成功,另一個(gè)就失敗了。

 

Redis 一般使用 setnx 實(shí)現(xiàn)分布式鎖,命令如下:

  1. SETNX KEY_NAME VALUE 

設(shè)置成功返回 1,設(shè)置失敗返回 0。使用單節(jié)點(diǎn)分布式鎖存在一些問題。

客戶端 1 獲取鎖后發(fā)生了故障:結(jié)果鎖就不能釋放了,其他客戶端永遠(yuǎn)獲取不到鎖。

解決方法是用下面命令對 key 設(shè)置過期時(shí)間:

  1. SET key value [EX seconds] [PX milliseconds] NX 

客戶端 2 誤刪除了鎖:解決方法是對 key 設(shè)置 value 時(shí)加入一個(gè)客戶端表示,比如在客戶端 1 設(shè)置 key 時(shí)在 value 前拼接一個(gè)字符串 application1,刪除的時(shí)候做一下判斷。

②Redis 紅鎖

Redis 單節(jié)點(diǎn)會(huì)有可靠性問題,節(jié)點(diǎn)故障后鎖操作就會(huì)失敗。Redis 為了應(yīng)對單點(diǎn)故障的問題,設(shè)計(jì)了多節(jié)點(diǎn)的分布式鎖,也叫紅鎖。

主要思想是客戶端跟多個(gè) Redis 實(shí)例請求加鎖,只有超過半數(shù)的實(shí)例加鎖成功,才認(rèn)為成功獲取了分布式鎖。

如下圖,客戶端分別跟 3 個(gè)實(shí)例請求加鎖,有 2 個(gè)實(shí)例加鎖成功,所以獲取分布式鎖成功:

 

緩存雪崩、擊穿、穿透

①緩存雪崩

Redis 做緩存時(shí),如果同一時(shí)間大量緩存數(shù)據(jù)失效,客戶端請求會(huì)大量發(fā)送到數(shù)據(jù)庫,導(dǎo)致數(shù)據(jù)庫壓力激增。

如下圖:

 

應(yīng)對方法主要有 3 個(gè):

  • 給 key 設(shè)置過期時(shí)間時(shí)加一個(gè)小的隨機(jī)數(shù)
  • 限流
  • 服務(wù)降級

②緩存擊穿

某個(gè)熱點(diǎn) key,突然過期了,大量請求發(fā)送到了數(shù)據(jù)庫。解決方案是給熱點(diǎn) key 不設(shè)置過期時(shí)間。

③緩存穿透

某個(gè)熱點(diǎn) key,查詢緩存和查詢數(shù)據(jù)庫都沒有,就發(fā)生了緩存穿透。

如下圖:

 

應(yīng)對方法主要有 2 個(gè):

  • 緩存熱點(diǎn)的空值和缺省值
  • 查詢數(shù)據(jù)庫之前先查詢布隆過濾器

數(shù)據(jù)傾斜

什么是數(shù)據(jù)傾斜?看下面這個(gè)面試題:如果 Redis 有一個(gè)熱點(diǎn) key,QPS 能達(dá)到 100w,該如何存儲(chǔ)?

如果這個(gè)熱點(diǎn) key 被放到一個(gè) Redis 實(shí)例上,這個(gè)實(shí)例面臨的訪問壓力會(huì)非常大。

如下圖,redis3 這個(gè)實(shí)例保存了 foo 這個(gè)熱點(diǎn) key,訪問壓力會(huì)很大:

 

解決方法主要有兩個(gè):

①使用客戶端本地緩存來緩存 key。

這樣改造會(huì)有兩個(gè)問題:

  • 客戶端緩存的熱點(diǎn) key 可能消耗大量內(nèi)存。
  • 客戶端需要保證本地緩存和 Redis 緩存的一致性。

②給熱點(diǎn) key 加一個(gè)隨機(jī)前綴,讓它保存到不同的 Redis 實(shí)例上。

這樣也會(huì)存在兩個(gè)問題:

  • 客戶端在訪問的時(shí)候需要給這個(gè) key 加前綴
  • 客戶端在刪除的時(shí)候需要根據(jù)所有前綴來刪除不同實(shí)例上保存的這個(gè) key

Bitmap 使用

有一道經(jīng)典的面試題,10 億整數(shù)怎么在內(nèi)存中去重排序?

我們先算一下 10 億整數(shù)占的內(nèi)存,Java 一個(gè)整數(shù)類型占四字節(jié),占用內(nèi)存大小約:

  1. 10億 * 4 / 1024 / 1024 = 3.7G 

占得內(nèi)存太大了,如果內(nèi)存不夠,怎么辦呢?

①Bitmap 介紹

Bitmap 類型使用的數(shù)據(jù)結(jié)構(gòu)是 String,底層存儲(chǔ)格式是二進(jìn)制的 bit 數(shù)組。假如我們有 1、4、6、9 四個(gè)數(shù),保存在 bit 數(shù)組中如下圖:

 

在這個(gè) bit 數(shù)組中用 10 個(gè) bit 的空間保存了四個(gè)整數(shù),占用空間非常小。

再回到面試題,我們使用 bit 數(shù)組長度是 10 億整數(shù)中 (最大值-最小值+1)。

如果有負(fù)數(shù),需要進(jìn)行一個(gè)轉(zhuǎn)化,所有數(shù)字加最小負(fù)數(shù)的絕對值。比如 {-2, 0, 1, 3},我們轉(zhuǎn)換成 {0, 2, 3, 5},因?yàn)閿?shù)組下標(biāo)必須從 0 開始。

②使用場景

員工打卡記錄:在一個(gè)有 100 個(gè)員工的公司,要統(tǒng)計(jì)一個(gè)月內(nèi)員工全勤的人數(shù),可以每天創(chuàng)建一個(gè) Bitmap,簽到的員工 bit 位置為 1。

要統(tǒng)計(jì)當(dāng)天簽到的員工只要用 BITCOUNT 命令就可以。

要統(tǒng)計(jì)當(dāng)月全勤的員工,只要對當(dāng)月每天的 Bitmap 做交集運(yùn)算就可以。

命令如下:

  1. BITOP AND srckey1 srckey2 srckey3 ... srckey30 

srckeyN 表示第 N 天的打卡記錄 Bitmap。

統(tǒng)計(jì)網(wǎng)站日活躍用戶:比如網(wǎng)站有 10 萬個(gè)用戶,這樣我們創(chuàng)建一個(gè)長度為 10 萬的 Bitmap,每個(gè)用戶 id 占一個(gè)位,如果用戶登錄,就把 bit 位置為 1,日終的時(shí)候用 BITCOUNT 命令統(tǒng)計(jì)出當(dāng)天登錄過的用戶總數(shù)。

作者:jinjunzhu

編輯:陶家龍

出處:轉(zhuǎn)載自公眾號程序員jinjunzhu

 

責(zé)任編輯:武曉燕 來源: 程序員jinjunzhu
相關(guān)推薦

2020-01-02 09:14:23

Kubernetes內(nèi)部容器

2022-02-16 18:00:19

動(dòng)態(tài)代理代碼靜態(tài)代理

2021-12-02 15:20:49

Redis數(shù)據(jù)結(jié)構(gòu)

2020-05-06 09:10:46

AQS同步器CAS

2021-10-22 09:28:15

開發(fā)技能代碼

2020-12-14 08:18:59

HTTPS信息安全

2022-12-26 08:36:24

JavaMESA模型

2020-03-26 10:25:26

工業(yè)互聯(lián)網(wǎng)IT工業(yè)物聯(lián)網(wǎng)

2020-03-27 15:49:17

工業(yè)物聯(lián)網(wǎng)技術(shù)5G

2020-03-26 10:33:36

工業(yè)互聯(lián)網(wǎng)概念

2020-11-02 12:50:29

分布式系統(tǒng)服務(wù)

2021-12-17 17:52:02

MySQL B+面試

2022-02-28 11:10:42

ZGCG1收集器

2020-07-02 09:15:59

Netty內(nèi)存RPC

2014-07-22 10:56:45

互聯(lián)網(wǎng)印度

2020-12-04 06:37:19

HTTPS原理安全

2021-02-01 11:30:13

React前端調(diào)度

2025-04-21 04:00:00

2020-12-14 10:15:03

負(fù)載均衡器Linux服務(wù)器

2022-03-07 17:43:30

注冊微服務(wù)架構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

2欧美一区二区三区在线观看视频 337p粉嫩大胆噜噜噜噜噜91av | 国产资源在线视频| 蜜桃久久一区二区三区| 亚洲综合好骚| xxxxxxxxx欧美| 久久人人爽人人片| 免费v片在线观看| 欧美高清一级片在线观看| 91精品在线播放| 亚洲天堂日韩av| 久久高清免费| 亚洲大胆人体视频| 在线观看免费污视频| 91制片在线观看| 中文字幕免费不卡| 国产一区二区精品免费| 伊人亚洲综合网| 亚洲网站视频| www.欧美精品一二三区| 国产精品九九九九九| 成人污污视频| 日本精品免费观看高清观看| 黄色一级片国产| 国产人成在线观看| 福利电影一区二区| 国产日韩专区在线| 亚洲欧美精品一区二区三区| 欧美在线高清| 中日韩午夜理伦电影免费| 国产免费一区二区三区最新6| 日本另类视频| 狠狠爱在线视频一区| 日韩video| 午夜在线播放| 久久精品一区二区三区av| 成人欧美一区二区三区视频| 亚洲永久精品视频| 日韩精品午夜视频| 国产91精品久| 国产污视频在线看| 一区二区影视| 啊v视频在线一区二区三区| 亚洲AV无码国产成人久久| 精品福利一区| 欧美va日韩va| 麻豆传媒在线看| 国产区一区二| 欧美一区在线视频| 久久久久久久久久久久久久久国产| 欧美一级大片| 91国产福利在线| 国产精品免费成人| 亚洲高清黄色| 日本乱码高清不卡字幕| 成年人网站大全| 婷婷激情一区| 在线精品视频小说1| 青青青在线播放| 日韩免费电影| 欧美午夜理伦三级在线观看| 激情婷婷综合网| 成人看片在线观看| 精品视频在线免费观看| 激情五月俺来也| 99精品国产九九国产精品| 91精品福利在线一区二区三区 | 国内精品在线播放| 91久久久久久久| 国内精品久久久久久久久久| 国产成人99久久亚洲综合精品| caoporn国产精品免费公开| 亚洲av综合色区无码一二三区 | 欧美日韩精品一二三区| 亚洲欧美在线精品| 国产精品一站二站| 精品福利一二区| 国产网站无遮挡| 精品国产乱码| 久久精品国产一区| 欧美日韩精品在线观看视频| 亚洲黄色av| 欧美专区福利在线| 日本一区二区三区久久| 国产精品一二二区| 精品视频在线观看| 18视频免费网址在线观看| 亚洲视频一二三区| 亚洲中文字幕无码av永久| 校园春色亚洲色图| 欧美一级理论片| 国产网站无遮挡| 91亚洲自偷观看高清| 欧美激情综合亚洲一二区| 精品美女久久久久| 久久99国产精品成人| 国产精品免费视频一区二区| 视频一区二区三区在线看免费看| 国产喷白浆一区二区三区| 大胆欧美熟妇xx| 欧美黑人一区| 日韩欧美久久一区| 美女被到爽高潮视频| 重囗味另类老妇506070| 青青草成人在线| av小说天堂网| 国产丝袜美腿一区二区三区| 在线观看17c| 影视一区二区三区| 精品少妇一区二区三区免费观看| 亚洲v国产v欧美v久久久久久| 中文字幕免费一区二区| 国产成人精品av在线| 亚洲AV无码一区二区三区性 | 亚洲国产高清自拍| 老司机福利在线观看| 日韩一区二区久久| 成人深夜直播免费观看| 欧美大片aaa| 亚洲最新视频在线观看| 日本久久精品一区二区| 精品视频自拍| 久久精品视频亚洲| 做爰无遮挡三级| 久久综合九色综合97婷婷| 高清无码视频直接看| 91成人app| 一区二区三区四区在线观看视频| 日本高清www免费视频| 国产乱码精品一品二品| 影音先锋欧美资源| 成人在线网站| 亚洲欧洲自拍偷拍| 国产三级av片| 99精品欧美一区二区三区小说| 日韩成人午夜影院| 亚洲二区av| 色综久久综合桃花网| 男人天堂视频在线| 久久久精品天堂| 国产免费成人在线| 日韩高清成人在线| 久久久久久亚洲| 国内爆初菊对白视频| 一区二区三区中文在线| 国产黄色一区二区三区 | 激情深爱综合网| 综合激情久久| 欧美老少配视频| 99精品在线看| 一卡二卡欧美日韩| 国产精品91av| 伊人久久大香线蕉综合热线| 97人人模人人爽视频一区二区| 91精选在线| 日韩欧美国产一区在线观看| 欧美色图亚洲视频| 国产精品18久久久久久久久久久久| 日本一级淫片演员| 欧美激情精品| 久久免费福利视频| 人妻无码中文字幕| 天天爽夜夜爽夜夜爽精品视频| 日本69式三人交| 国产欧美另类| 日韩av高清在线播放| av在线一区不卡| 精品国产区一区二区三区在线观看| 一卡二卡三卡在线| 亚洲精品成人天堂一二三| 国产吃瓜黑料一区二区| 99国产精品久久久久久久| 麻豆亚洲一区| 久久天堂影院| 久久99久久亚洲国产| 亚洲AV无码一区二区三区性| 欧美日韩国产丝袜另类| 欧美丰满美乳xxⅹ高潮www| 日本女优在线视频一区二区 | 免费看的黄色欧美网站| 色一情一乱一伦一区二区三欧美| 香蕉久久一区| 久久久久久久久久久91| 国产免费av高清在线| 91.麻豆视频| 欧美日韩在线视频免费播放| 99精品欧美一区二区三区综合在线| 亚洲少妇第一页| 综合激情网站| 青娱乐一区二区| 国产精品xnxxcom| 57pao成人永久免费视频| 在线观看黄色av| 精品国产乱码久久久久久夜甘婷婷 | 91精产国品一二三| 久久国产成人| 成人性做爰片免费视频| 亚洲欧洲av| 亚洲一区二区三区视频播放| 这里有精品可以观看| 久久精品一偷一偷国产| 天天色综合av| 91精品欧美一区二区三区综合在| 日韩欧美高清在线观看| 中文字幕人成不卡一区| 欧美无人区码suv| 激情综合网激情| 国产成人a亚洲精v品无码| 午夜免费一区| 日韩成人av网站| 久久国产精品免费精品3p| 国产伦精品一区二区三区精品视频| 成人免费高清观看| 日韩网站免费观看| 欧美女子与性| 亚洲第一精品福利| 国产乱码精品一区二三区蜜臂| 欧美视频在线免费| 久久久无码精品亚洲国产| 中文字幕中文字幕一区二区| 国产吞精囗交久久久| 成人午夜视频网站| 亚洲一二三不卡| 美腿丝袜在线亚洲一区 | 欧美高清视频一区二区三区| 欧美激情一二三区| 成人性生交大免费看| 成人免费不卡视频| 久久精品一卡二卡| 蜜臀精品久久久久久蜜臀| 色综合av综合无码综合网站| 在线日韩视频| 日韩免费在线观看av| 久久精品影视| 异国色恋浪漫潭| 日韩久久久久| 亚洲春色在线| 欧美三级情趣内衣| 欧美1o一11sex性hdhd| 日韩高清成人在线| 久久国产欧美精品| 欧美色资源站| 精品日产一区2区三区黄免费| jizz性欧美23| 国产欧美一区二区三区不卡高清| 亚洲一区二区三区日本久久九| 91久久在线视频| 99精品视频在线免费播放 | 国产色片在线观看| 欧美年轻男男videosbes| 亚洲一卡二卡在线| 91.成人天堂一区| 91麻豆国产视频| 制服视频三区第一页精品| 国产精品女同一区二区| 欧美一区二区三区四区五区| 国产麻豆91视频| 日韩一级完整毛片| 韩国av永久免费| 日韩精品中文字幕在线| 精品999视频| 少妇高潮 亚洲精品| 黄色网页在线免费看| 九九热精品在线| heyzo高清在线| 欧美在线视频播放| 91精品影视| 日韩激情av在线免费观看| 亚洲国产小视频在线观看| 国产1区2区3区4区| 夜夜嗨av一区二区三区四季av| 美女福利视频在线观看| 亚洲影院免费观看| 日韩精品在线观看免费| 日本韩国欧美一区| 在线观看av大片| 日韩欧美一级二级三级| 欧美 日韩 国产 成人 在线| 亚洲国内精品在线| 你懂的视频在线免费| 中文字幕最新精品| 成人福利网站| 97精品在线观看| 97精品国产99久久久久久免费| 成人午夜高潮视频| 黄色欧美在线| 亚洲一区二区免费视频软件合集| 午夜精品电影| 国产视频一区二区三区在线播放| 久久99精品久久久| 日本一区二区在线免费观看| 中文字幕免费一区| 精品午夜福利在线观看| 色偷偷成人一区二区三区91| 国产精品永久久久久久久久久| 亚洲高清免费观看高清完整版| аⅴ资源新版在线天堂| 欧美另类极品videosbestfree| 在线天堂中文资源最新版| 亚洲在线观看视频| 欧美理论在线播放| 国产精品日韩三级| 日韩综合一区二区| 精品久久久久一区二区| 欧美国产精品v| 好吊妞视频一区二区三区| 91精品国产91久久久久久一区二区 | 亚洲欧美日韩精品一区二区| 在线观看日本一区二区| 99精品黄色片免费大全| 黄色片子在线观看| 在线观看精品一区| 涩涩视频免费看| 久久成人免费视频| 五月激情久久| 精品国产aⅴ麻豆| 欧美成人精品| 性欧美1819| 久久久亚洲午夜电影| 久久99久久98精品免观看软件| 欧美日韩小视频| 日本成人一区| 欧美精品久久久久久久免费观看| 日本亚洲欧洲无免费码在线| 欧美人xxxxx| 在线亚洲一区| 亚洲无人区码一码二码三码| 亚洲色图欧洲色图婷婷| 中文字幕人妻互换av久久| 亚洲精品在线视频| av中文字幕在线看| 97超级碰碰| 欧美一区二区三区另类| 老司机久久精品| 国产精品伦理在线| 中文字幕免费在线看| 亚洲欧美日韩直播| 三妻四妾完整版在线观看电视剧| 国产成人精品自拍| 欧美日韩午夜| www.欧美com| 亚洲综合成人网| 午夜久久久久久久久久| 久久在线视频在线| 精品久久免费| 日韩 欧美 自拍| 国产精品夜夜嗨| 麻豆一区二区三区精品视频| 欧美成va人片在线观看| 羞羞视频在线观看免费| 99久久自偷自偷国产精品不卡| 欧美一区二区三区久久精品茉莉花| 午夜免费视频网站| 亚洲精品国久久99热| 高潮毛片7777777毛片| 欧美激情精品久久久久久免费印度 | 色老头久久综合| 国产在线观看网站| 国产精品美女主播在线观看纯欲| 日韩一区三区| 国产成人强伦免费视频网站| 亚洲夂夂婷婷色拍ww47| 天天摸天天干天天操| 国产成人精品最新| 日韩激情免费| 亚洲精品一区二区18漫画| 亚洲国产欧美在线| 欧美一区二区三区少妇| 国产精品久久久久免费a∨| 四虎国产精品免费观看| 精品国产鲁一鲁一区二区三区| 亚洲一区在线视频观看| 中文字幕一区二区三区四区在线视频| 成人av资源在线观看| 国产精品suv一区二区三区| 亚洲丝袜一区在线| 亚洲午夜剧场| 亚洲色成人www永久在线观看| 91免费观看视频| 在线观看国产黄| 九九热r在线视频精品| 欧美三级午夜理伦三级在线观看 | 国产精品一级片在线观看| 国产乡下妇女做爰视频| 亚洲色图国产精品| 国产精品1区在线| 鲁一鲁一鲁一鲁一澡| 国产精品―色哟哟| 亚洲黄色小说网| 国产精品99久久久久久人| 91精品国产成人观看| 丰满大乳奶做爰ⅹxx视频 | 做a视频在线观看| 亚洲午夜电影在线观看| 国产原创av在线| 91精品天堂| 久久精品系列| 青青草偷拍视频| 中文字幕欧美日韩va免费视频| 麻豆精品久久| 激情综合网俺也去|