面試疑問
寫在前面,看過本文,讓那些沒使用過redis的也能回答上來面試官的問題,不至于陷入太尷尬的境地!因為現在好多面試官不單單只是問你,用沒用過redis,而是會一直問下去,比如:你項目里面用redis做什么?里面放什么數據?什么類型?對于list類型的數據,我更改了一個如何高效率的刷新redis緩存?
帶著這些疑問我們下面去討論。希望各位大佬勇于補充。
Redis簡介:
如大家所知道的一樣,Redis是一個開源的使用ANSI C語言編寫、支持網絡、可基于內存亦可持久化的日志型、Key-Value數據庫(區別于MySQL等關系型數據庫),并提供多種語言的API調用方案。
Redis存儲數據結構:
一共支持五種數據類:
string(字符串)
hash(哈希)
list(列表)
set(集合)
zset(sorted set有序集合)。
Redis內存占用情況:
測試情況:90萬個鍵值對(鍵是0到899999值是字符串“hello world”)在32位操作系統的筆記本上 用了90MB,但是使用64位的操作系統的話,相對來說占用的內存會多一點,這是因為64位的系統里指針占用了8個字節,但是64位系統也能支持更大的內存,所以運行大型的redis服務還是建議使用64位服務器。
堅持一個原則:使用數據庫能解決的業務場景,就不要使用REDIS。
Redis使用場景:
- 排行榜
- 序列號
- 計數器
- 流水號
- 驗證碼
- 用戶信息
- token
- 菜單
- 最新列表
- 關注列表
- 分布式鎖與單線程機制
下面具體說下每個數據類型的使用場景,也好應付面試官的隨機發問。
- Zset使用場景
- 數據結構:ZSET
- 關鍵API:zadd、zincrBy、zrevrank、zscore、zrevrangeWithScores
- 場景:金主榜、活動昨日榜、今日榜、本周榜、上周榜
- String使用場景
- 數據結構:STRING
- 關鍵API:incr、decr、set、get
- 場景:點贊數、驗證碼(過期時間)、token
- 用于數據量上億的場景下,例如幾億用戶系統的簽到,去重登錄次數統計,某用戶是否在線狀態等等。
- 數億用戶,要幾個毫秒內查詢到某個用戶是否在線?
- 原理是:redis內構建一個足夠長的數組,每個數組元素只能是0和1兩個值,下標index用來表示用戶id(必須是數字),那么很顯然,這個幾億長的大數組就能通過下標和元素值(0和1)來構建一個記憶系統,上面我說的幾個場景也就能夠實現。
- Hash使用場景
- 數據結構:HASH
- 關鍵API:hget、hset、hgetall
- 存儲部分變更數據如用戶信息等
- SET使用場景
- 數據結構:SET
- 關鍵API:sadd、spop、smembers、sunion、sinter
- 場景:關注列表、粉絲列表
- 可以將一個用戶所有的關注人存在一個集合中,將其所有粉絲存在一個集合。Redis還為集合提供了求交集、并集、差集等操作,可以非常方便的實現如共同關注、共同喜好、二度好友等功能,對上面的所有集合操作。
- Set是集合,是String類型的無序集合,set是通過hashtable實現的,概念和數學中個的集合基本類似,可以交集,并集,差集等等,set中的元素是沒有順序的。
名詞解釋:
- 緩存穿透
緩存穿透是指查詢一個一定不存在的數據,由于緩存是不命中時被動寫的,并且出于容錯考慮,如果從存儲層查不到數據則不寫入緩存,這將導致這個不存在的數據每次請求都要到存儲層去查詢,失去了緩存的意義。在流量大時,可能DB就掛掉了。
業界比價普遍的一種做法,即根據key獲取value值為空時,鎖上,從數據庫中load數據后再釋放鎖。若其它線程獲取鎖失敗,則等待一段時間后重試。這里要注意,分布式環境中要使用分布式鎖,單機的話。用普通的鎖(synchronized、Lock)就夠了。
- 緩存雪崩
緩存在同一時間內大量鍵過期(失效),接著來的一大波請求瞬間都落在了數據庫中導致連接異常。