自己實戰整理面試題--Redis(帶答案,不斷更新)
Redis應用場景?
分散式鎖:通過setnx/del命令來實現,不完美的是由於業務場景比較多,所以,有些瑕疵,比如:setnx/del命令是非原子性的,存在執行完setnx但是沒有執行del的情況,導致鎖無法釋放,針對這種情況Redis的團隊加入了一些引數特性,給鎖加上過期時間,我的理解時間到了等於鎖被釋放了和del的命令作用一致,但是這個時間到底設定多久好呢?如果設定的比較短,鎖過期了,業務還沒執行完,同樣會出現執行程式碼錯亂的問題,於是針對這種業務場景的問題,想到了給value值加隨機數的解決方案,誰加的鎖,誰來解,不過問題又來了,判斷value的值和del也不是原子性的,如果判斷該解鎖了,但是出現某種異常導致沒有執行del,還是會存在解鎖失敗的問題,好像無解了!後面又有了使用lua指令碼的方式的解決方案,再往後又提到了可重入鎖的解決方案,多次獲取同一把鎖,延長一些加鎖時間,然後在釋放鎖。
延時佇列:list(列表) 資料結構常用來作為非同步訊息佇列使用,使用rpush/lpush
操作入佇列,使用lpop 和 rpop
來出佇列。
問題:佇列空了,佇列延遲( zset(有序列表) 來實現),空閒連線自動斷開,鎖衝突處理
簽到:點陣圖bitmap, (setbit) 和獲取 (getbit) 指定位的值都是單個位的,如果要一次操作多個位,就必須使用管道來處理,bitfield 有三個子指令,分別是 get/set/incrby,它們都可以對指定位片段進行讀寫,但是最多隻能處理 64 個連續的位,如果超過 64 位,就得使用多個子指令,bitfield 可以一次執行多個子指令.
PV,UV統計:HyperLogLog(精度不高):兩個指令 pfadd 和 pfcount,根據字面意義很好理解,一個是增加計數,一個是獲取計數。pfadd 用法和 set 集合的 sadd 是一樣的,來一個使用者 ID,就將使用者 ID 塞進去就是。pfcount 和 scard 用法是一樣的,直接獲取計數值。
pf 的記憶體佔用為什麼是 12k? Redis 的 HyperLogLog 實現中用到的是 16384 個桶,也就是 2^14,每個桶的 maxbits 需要 6 個 bits 來儲存,最大可以表示 maxbits=63,於是總共佔用記憶體就是2^14 * 6 / 8 = 12k位元組。
推薦去重:布隆過濾器(有誤差):二個基本指令,bf.add 新增元素,bf.exists 查詢元素是否存在,它的用法和 set 集合的 sadd 和 sismember 差不多。注意 bf.add 只能一次新增一個元素,如果想要一次新增多個,就需要用到 bf.madd 指令。同樣如果需要一次查詢多個元素是否存在,就需要用到 bf.mexists 指令。
限流,控制流量,控制使用者行為:滑動視窗zset;使用 pipeline 可以顯著提升 Redis 存取效率
用incrby存在問題:假設現在有個介面, 限制5秒內只能訪問10次, 在第一秒訪問了, 然後設定過期時間, 然後在最後一秒內, 一下訪問了8次, 但是下一秒就過期了, 過期之後又一下子來了8條記錄, 這個時候就沒有限流住了, 導致2秒內訪問了16次介面。
UGC:漏斗限流Redis-Cell:
地圖座標: Geo,本質是zset,提供一些特殊的指令。針對附近的人、醫院、銀行、餐館、公園、交通站等問題。
redis底層框架 模型
Redis為什麼這麼快?redis採用多執行緒會有哪些問題?
Redis支援哪幾種資料結構;
Redis跳躍表的問題;
Redis單程序單執行緒的Redis如何能夠高併發?
Redis如何使用Redis實現分散式鎖?
Redis分散式鎖操作的原子性,Redis內部是如何實現的?
用hashmap實現redis有什麼問題(死鎖,死迴圈,可用ConcurrentHashmap)