作者:沙茶敏碎碎念
眾所周至,拼多多的待遇也是高的可怕,在挖人方面也是不遺余力,對於一些工作 3 年的開發,稍微優秀一點的,都給到 30K 的 Offer。
當然,拼多多加班也是出名的,一周上 6 天班是常態,每天工作時間基本都是超過 12 個小時,也是相當辛苦的。
廢話不多說,今天我們來聊一聊拼多多的一道后台面試真題,是一道簡單的架構類的題目:
拼多多有數億的用戶,那么對於某個網頁,怎么使用 Redis 來統計一個網站的用戶訪問數呢?
使用 Hash
哈希是 Redis 的一種基礎數據結構,Redis 底層維護的是一個開散列,會把不同的 key 映射到哈希表上,如果是遇到關鍵字沖突,那么就會拉出一個鏈表出來。
當一個用戶訪問的時候,如果用戶登陸過,那么我們就使用用戶的 id,如果用戶沒有登陸過,那么我們也能夠前端頁面隨機生成一個 key 用來標識用戶。
當用戶訪問的時候,我們可以使用 HSET 命令,key 可以選擇 URI 與對應的日期進行拼湊,field 可以使用用戶的 id 或者隨機標識,value 可以簡單設置為 1。
當我們要統計某一個網站某一天的訪問量的時候,就可以直接使用 HLEN 來得到最終的結果了。
優點:簡單,容易實現,查詢也是非常方便,數據准確性非常高。
缺點:占用內存過大,隨着 key 的增多,性能也會下降。小網站還行,拼多多這種數億 PV 的網站肯定受不了
使用 Bitset
我們知道,對於一個 32 位的 int,如果我們只用來記錄 id,那么只能夠記錄一個用戶,但如果我們轉成 2 進制,每位用來表示一個用戶,那么我們就能夠一口氣表示 32 個用戶,空間節省了 32 倍!
對於有大量數據的場景,如果我們使用 bitset,那么,可以節省非常多的內存。
對於沒有登陸的用戶,我們也可以使用哈希算法,把對應的用戶標識哈希成一個數字 id。
bitset 非常的節省內存,假設有 1 億個用戶,也只需要 100000000/8/1024/1024 約等於 12 兆內存。
Redis 已經為我們提供了 SETBIT 的方法,使用起來非常的方便。
我們可以看看下面的例子:
我們在 item 頁面可以不停地使用 SETBIT 命令,設置用戶已經訪問了該頁面,也可以使用 GETBIT 的方法查詢某個用戶是否訪問。
最后我們通過 BITCOUNT 可以統計該網頁每天的訪問數量。
優點占用內存更小,查詢方便,可以指定查詢某個用戶,數據可能略有瑕疵,對於非登陸的用戶,可能不同的 key 映射到同一個 id,否則需要維護一個非登陸用戶的映射,有額外的開銷。
缺點如果用戶非常的稀疏,那么占用的內存可能比方法一更大。
使用概率算法
對於拼多多這種多個頁面都可能非常多訪問量的網站,如果所需要的數量不用那么准確,可以使用概率算法,事實上,我們對一個網站的 UV 的統計,1 億跟 1 億零 30 萬其實是差不多的。
在 Redis 中,已經封裝了 HyperLogLog 算法,他是一種基數評估算法。
這種算法的特征,一般都是數據不存具體的值,而是存用來計算概率的一些相關數據。
當用戶訪問網站的時候,我們可以使用 PFADD 命令,設置對應的命令,最后我們只要通過 PFCOUNT 就能順利計算出最終的結果,因為這個只是一個概率算法,所以可能存在 0.81% 的誤差。
優點占用內存極小,對於一個 key,只需要 12kb。對於拼多多這種超多用戶的特別適用。
缺點查詢指定用戶的時候,可能會出錯,畢竟存的不是具體的數據。總數也存在一定的誤差。
好了,上面就是常見的 3 種適用 Redis 統計網站用戶訪問數的方法了。
原文鏈接:
www.toutiao.com/i6695734985246114312/
·END·
程序員的成長之路
路雖遠,行則必至
本文原發於 同名微信公眾號「程序員的成長之路」,回復「1024」你懂得,給個贊唄。
回復 [ 520 ] 領取程序員最佳學習方式
回復 [ 256 ] 查看 Java 程序員成長規划