精品欧美一区二区三区在线观看 _久久久久国色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ù)棧公眾號

色噜噜狠狠成人中文综合| 成人黄色av网站在线| 色噜噜亚洲精品中文字幕| 中文字幕在线综合| 污视频在线看网站| 91性感美女视频| 国产中文欧美精品| 日本少妇在线观看| 国产一区二区观看| 日韩欧美在线123| avav在线看| 国产区在线观看| 91丨九色丨尤物| 成人免费淫片aa视频免费| 国产香蕉在线视频| 97精品国产福利一区二区三区| 精品少妇一区二区| 国产区二区三区| free性欧美16hd| 国产精品美女久久久久久| 国产精品嫩草在线观看| 91高潮大合集爽到抽搐| 国产精品久久久久久模特| 久久精品国产亚洲| 午夜理伦三级做爰电影| 在线精品国产亚洲| 欧美日韩二区三区| 日韩精品一区二区三区久久| 午夜小视频在线观看| 日本一区二区不卡视频| 久久99精品国产99久久| 国产精品一区二区三区在线免费观看| 国产精品乱看| 欧美极品欧美精品欧美视频| 日韩欧美国产成人精品免费| 精品国产一区二区三区噜噜噜 | 成人免费观看cn| 操你啦在线视频| 中文字幕第一区二区| 欧美日韩一区二区视频在线观看 | 激情图区综合网| 日本欧美中文字幕| 五月天婷婷激情| 亚洲区欧美区| 久久久女女女女999久久| 欧美a级片免费看| 久久免费av| 国产午夜精品视频免费不卡69堂| 丰满少妇在线观看资源站| 国产劲爆久久| 亚洲电影成人av99爱色| 亚洲熟女乱综合一区二区| 国产高清视频一区二区| 欧美日韩一区 二区 三区 久久精品| 久久人妻精品白浆国产| 日本在线啊啊| 午夜欧美在线一二页| 国产精品va在线观看无码| yellow91字幕网在线| 中文字幕永久在线不卡| 天堂v在线视频| 日本www在线| 成人免费视频在线观看| 永久免费精品视频网站| 亚洲图片88| 亚洲欧美综合另类在线卡通| 一区不卡字幕| 欧美成人性生活视频| 国产精品欧美综合在线| 制服丝袜综合日韩欧美| av免费在线免费观看| 一区二区成人在线观看| 国内精品久久久久久久影视蜜臀| 欧美日韩的一区二区| 国产原创精品在线| 亚洲精品777| 欧美一级片在线看| 亚洲av综合色区无码另类小说| www国产精品| 日韩成人在线免费观看| 亚洲第九十七页| 欧美丝袜激情| 久久精品99久久久香蕉| 久久精品99久久久久久| 99综合精品| 国产精品美女网站| 国产三级小视频| 成人高清在线视频| 日韩精品久久久毛片一区二区| 亚洲成人三级| 亚洲黄色录像片| 18禁免费无码无遮挡不卡网站| 91精品xxx在线观看| 欧洲国产伦久久久久久久| 亚洲欧美天堂在线| 久久久免费毛片| 在线看欧美日韩| 欧美三级免费看| 免费亚洲网站| 99re国产| 韩国福利在线| 一区二区三区不卡在线观看| 男人的天堂99| 日韩精品一区二区三区中文字幕| 日韩精品视频在线播放| 国产小视频你懂的| 亚洲国产激情| 成人国产精品免费视频| 无码精品视频一区二区三区| 国产精品另类一区| 成人一对一视频| 97久久中文字幕| 亚洲欧洲国产伦综合| 欧美日韩偷拍视频| 日本在线观看不卡视频| 翡翠波斯猫1977年美国| 免费在线超碰| 亚洲国产视频网站| 污污网站免费观看| 无码少妇一区二区三区| 欧美成年人在线观看| 欧美一级淫片免费视频黄| 懂色一区二区三区免费观看| 亚洲不卡一卡2卡三卡4卡5卡精品| 主播国产精品| 欧美日韩1区2区| 一级片手机在线观看| 国产一区久久| 国产在线a不卡| 撸视在线观看免费视频| 亚洲mv大片欧洲mv大片精品| 超碰中文字幕在线观看| 欧美va久久久噜噜噜久久| 欧美有码在线观看视频| 日本人妻丰满熟妇久久久久久| 中文字幕在线免费不卡| 成人中文字幕av| 亚洲人成精品久久久| 久久久久久久久久久免费 | 久久天天综合| 久久精品国产美女| а√天堂中文在线资源8| 欧美一级欧美一级在线播放| www.com.av| 麻豆成人免费电影| 亚洲精品无人区| 日韩欧美一区二区三区在线观看| 亚洲免费电影一区| 国产性猛交╳xxx乱大交| 成人va在线观看| 成人精品视频在线播放| av成人男女| 久久久久女教师免费一区| 成人福利小视频| 亚洲国产综合在线| 免费黄色a级片| 亚洲二区在线| 精品免费日产一区一区三区免费| 国产直播在线| 日韩精品在线观看视频| www五月天com| 国产欧美日韩激情| 色乱码一区二区三区在线| 手机在线电影一区| 92看片淫黄大片看国产片| 污污网站在线看| 亚洲二区中文字幕| 国产91精品一区| 国产视频一区二区在线| 手机看片一级片| 91九色精品| 98国产高清一区| 爱福利在线视频| 亚洲片在线观看| 一本久道久久综合无码中文| 亚洲欧美偷拍三级| 日本精品一二三| 在线亚洲观看| 亚洲午夜精品国产| 欧美一区一区| 欧美诱惑福利视频| melody高清在线观看| 欧美精品99久久久**| 免费在线观看亚洲| 久久久精品综合| 国产美女视频免费看| 亚洲激精日韩激精欧美精品| 蜜桃久久精品乱码一区二区| 99只有精品| 久久久噜噜噜久久中文字免| 蜜桃成人在线视频| 日韩一区和二区| 国产无人区码熟妇毛片多| 欧美激情一区二区三区| 红桃视频一区二区三区免费| 国产欧美二区| dy888午夜| 国产精品欧美在线观看| 亚洲aⅴ日韩av电影在线观看| 国产美女高潮在线| 精品久久久av| 欧美女优在线| 日韩精品专区在线影院重磅| 99re国产在线| 一二三四区精品视频| 先锋影音av在线| 国产99久久久精品| 婷婷免费在线观看| 亚洲一区二区动漫| 国产爆乳无码一区二区麻豆| 欧美肉体xxxx裸体137大胆| 99久久精品免费看国产四区| 影音成人av| 91精品国产91久久久久久最新| 国产三区在线观看| 国产一区二区三区精品久久久| 免费观看国产精品| 69堂成人精品免费视频| 中文字幕av第一页| 香蕉成人啪国产精品视频综合网| 亚洲一级二级片| 亚洲国产精品黑人久久久| 91精品啪在线观看国产| 国产在线不卡视频| 国产又粗又长又大的视频| 亚洲一区中文| 欧美一级视频免费看| 欧美日韩1区| 欧美日韩一级在线| 日韩免费在线| 日韩欧美亚洲日产国| 欧洲亚洲成人| 国内精品视频在线播放| 精品国产一区二区三区2021| 国产一区视频在线| 99久久伊人| 国产精品白丝jk喷水视频一区 | 天天射,天天干| 91精品国产高清一区二区三区| 亚洲精品一区二区二区| 色欧美乱欧美15图片| 久久久久久少妇| 天天色综合成人网| 国产精品免费av一区二区| 亚洲综合一二区| 黄色一级片在线| 一区二区免费在线| 久久国产精品二区| 亚洲妇熟xx妇色黄| 国产精彩视频在线| 亚洲成人激情综合网| 日本天堂网在线观看| 亚洲成a人片综合在线| 久久久91视频| 亚洲国产精品久久不卡毛片| 久艹视频在线观看| 亚洲一区二区三区中文字幕 | 国产高清久久| 一区二区三区国产福利| 91精品天堂福利在线观看| 一级一片免费播放| 女生裸体视频一区二区三区| 2021国产视频| 亚洲国产日韩欧美一区二区三区| 3d动漫一区二区三区| 国产午夜久久| 国产嫩草在线观看| 国内成人精品2018免费看| 天天色天天干天天色| 国产成人小视频| 9.1成人看片| 久久精品一区二区三区av| 欧美激情 一区| 亚洲欧美日韩中文播放| 久久国产美女视频| 午夜久久久久久| 色av性av丰满av| 在线播放中文字幕一区| 亚洲成人黄色片| 精品亚洲aⅴ在线观看| 99中文字幕一区| 欧美成人午夜剧场免费观看| 2020日本在线视频中文字幕| 国产精品1234| 日本精品在线播放| 欧美午夜精品久久久久久蜜| 欧美激情欧美| 人妻夜夜添夜夜无码av| 另类国产ts人妖高潮视频| 亚洲欧美久久久久| 成人黄色av电影| 美国美女黄色片| 亚洲444eee在线观看| 日本成人一级片| 日韩欧美国产午夜精品| 三级在线播放| 久久中文字幕视频| 另类专区亚洲| 91视频婷婷| 精品国产成人| 很污的网站在线观看| 久久精品久久精品| 欧美成人三级伦在线观看| 综合久久综合久久| 婷婷激情五月网| 日韩色视频在线观看| 黄色小视频在线观看| 国模精品系列视频| 欧美精品高清| 狠狠色伊人亚洲综合网站色| 性xxxx欧美老肥妇牲乱| 凹凸日日摸日日碰夜夜爽1| 国产精品亚洲第一区在线暖暖韩国| 日本二区在线观看| 亚洲国产cao| 国产乱淫片视频| 亚洲最大在线视频| 国产欧洲在线| 97久草视频| 久久激情电影| 国产精品第12页| 99久久精品国产毛片| 加勒比婷婷色综合久久| 欧美日韩色一区| 黄色小视频在线免费观看| 91精品国产91久久久久久| 日韩不卡在线视频| 欧美日韩在线免费观看视频| 日本欧美久久久久免费播放网| 中国黄色a级片| 午夜精品福利久久久| a天堂视频在线| 久久天天躁狠狠躁夜夜躁2014| 韩日精品一区| 色综合666| 丝袜诱惑制服诱惑色一区在线观看| 国产精品熟妇一区二区三区四区 | 亚洲免费一在线| 国产免费拔擦拔擦8x高清在线人| 国产精品国产亚洲精品看不卡15| 欧美黄色一区| 国产精品熟女一区二区不卡| 亚洲欧美日韩一区二区 | 鲁鲁在线中文| 国产精品一区二区免费| 欧美成人一区二免费视频软件| 怡红院亚洲色图| 国产精品久久久久久户外露出| 国产91av在线播放| 一区二区三区四区精品| 巨胸喷奶水www久久久免费动漫| 日韩国产一区久久| 日韩av一二三| 开心激情五月网| 欧美一区二区播放| 手机电影在线观看| 国产视频在线观看一区| 亚洲黄色影院| 不卡一区二区在线观看| 色综合 综合色| av二区在线| 成人黄色免费片| 午夜精品av| 催眠调教后宫乱淫校园| 婷婷综合另类小说色区| 欧美亚洲日本| 国产精品久久久久免费a∨大胸 | 999一区二区三区| 成人午夜av在线| 亚洲欧美偷拍视频| 中文字幕亚洲欧美一区二区三区| 亚洲成a人片777777久久| 欧美另类videos| av不卡在线播放| www.av88| 美女精品久久久| 欧美调教在线| www.com操| 亚洲一区二区在线免费观看视频| 涩涩视频免费看| 国产精品久久久久久久久久小说 | 亚洲无码精品在线播放| 久久综合久久88| 欧美综合精品| 欧美成人福利在线观看| 亚洲午夜精品一区二区三区他趣| 日韩欧美在线观看一区二区| 国产欧美日韩视频| 韩日在线一区| 我不卡一区二区| 精品电影一区二区| 3d欧美精品动漫xxxx无尽| 欧美日韩中文字幕在线播放| 91亚洲精品久久久蜜桃网站| 在线观看国产一区二区三区| 欧美国产在线视频| blacked蜜桃精品一区| 97中文字幕在线观看| 色婷婷av一区二区三区软件 | 茄子视频成人在线|