今天這個問題比較初級,很多同學應該可能都知道,即便是沒吃過豬肉,也應該見過豬跑。廢話不多說,步入正題。
小提示,redis是使用C語言實現的。
字符串
第一種數據就是字符串,也就是string,這是redis中最基礎的數據類型了,最起碼redis中所有的key本身都是字符串類型。
我舉幾個常見的場景:
- 這個東西用處就比較廣了。如果一個數據表數據量過千萬了,而你的業務需要反復count表的總數,這個操作是很耗費性能的,這會兒你就可以用string字符串來緩存這個總數
- 如果你需要一個計數器,那么也可以利用字符串類型,因為字符串類型有一個incr操作,可以在收到操作后將數字+1
- 有些博客中還說將用戶信息也存到字符串中,我認為這很腦殘。因為要往字符串中存用戶數據,你就必須得先將用戶信息序列化了之后才能存儲到字符串中,用的時候,你還得反序列化,我認為這不科學
字符串在redis中實現本質上講就是c語言的字符串,但是大家知道C語言中實際上壓根沒有字符串這種數據類型,對C語言來說字符串也就是一坨字符+一個\0結束符。redis中的字符串要比單純的C語言字符串要稍微復雜一些,叫做SDS。redis的SDS除了保存字符串本身外,還有該字符串的長度,以及尚未使用完剩余的空間長度。當你使用redis中strlen來獲取一個字符串長度的時候,實際上就是直接讀取的長度屬性,所以在O(1)時間復雜度情況下讀出長度。先到此為止,不能扯太深的SDS,放到后面。
list
第二種數據結構就是list,也就是鏈表。你們先記住了,redis的list本質上是一個雙向鏈表,雙向鏈條的意思就是組成鏈表的每個節點中,有一個指向前面節點的指針,也有一個指向后面節點的指針,穿成了一串。
- 充當簡單的消息隊列。我們知道list有四個風騷的操作,在list的頭部添加元素或刪除元素,在list在尾部添加元素或刪除元素,利用這個特性我們可以利用list來充當一個簡單的消息隊列,避免了很多同學不懂rabbitmq、kafka之類的高端玩意
- 做簡單的搶購秒殺。比如搶購10個元素,那么可以預先向list中插入10個任意元素,每搶到一個就rpop一下,當list中什么都沒有了的話,rpop值就是false,這會兒就算搶購完畢了。有同學有疑問,說利用字符串保存一個計數器不是也能搶購嗎?並不能,你一定是這么想的,比如你存了一個counter數值是10,每搶到一次就減1,一直到0,是吧。但是你為了實現這個邏輯一定有兩個分開的關鍵操作,一個判斷counter大小,另一個是減1,這個時候在並發大的時候會出現一種可能性,就是當一個路人甲用戶判斷完counter為1后,還剩最后一個庫存,於是就准減1了,但是恰巧,在路人甲對counter減1之前完成前,又來了一個路人乙用戶也剛執行完了判斷counter,由於路人甲還沒有減1,所以路人乙判斷的counter也一定是1,那么,超賣就產生了
無序集合
第三種數據是set,這是一種無序集合,集合中只能存數字,而且不會重復,也就是說如果你反復存了兩個數字22,那么最終也會只有一個22,所以set有兩大特征:無序和唯一!set在redis中實現本質上就是一個struct結構體,如果你不知道struct是啥,那就簡單點兒,其實就是一個整數數組,還有一個數組長度。所以,獲取set中元素數量的時候,對於redis是輕而易舉的,O(1)內拿下!
- set最厲害的地方就是求交集、求差集以及並集。所以當我們查看兩個人共同好友的時候,可以迅速獲取到。
- 大家都玩過探探吧,左滑右滑,單凡滑過的人都不會再次出現,那么如何記錄你曾經滑過的人呢?我認為set就可以大放異彩了。然后比如著名社交軟件,積目,就是靠這個實現的,是不是很垃圾?
有序結合
第四種數據結構是zset,叫做有序結合,zset中的數據可以重復,所以zset有兩大特征,一是可以重復,二是這些數據是有序的並且可以排序。利用這個特征,我們可以知道zset中的數據是可以分頁的!一定要記住!zset中的數據可以分頁!zset在redis中實現本質上就是skiplist,也就是傳輸中的跳表,不懂可以先記住!之所以具備有序特性,也完全是因為跳表本身的特性。跳表的結構是redis常見數據結構比較復雜的了,至少在我看來是這樣的。具體結構我們放到后面解析。
- zset可以做什么?粉絲列表。因為粉絲列表查看粉絲是需要按照關注時間倒序進行排列的,而且還可以分頁!這個就很屌!
- 排行榜。比如我們要做一個積分用戶榜單,當然使用mysql也可以使用order by來解決,但是利用redis顯然是更快更猛。
哈希
第五種數據結構是字典了,這種數據結構很類似於php的數組,專門用於存放一坨key=》value鍵值對。字典這個東西在redis中的C語言實現就是哈希這個著名的數據結構,不理解是吧,先背過,后面有解析,你記住了知道了就比不知道強。
- 前面說了,用字符串來存儲序列化后的用戶數據是愚蠢的,原因就是有現成的字典,用這個就是絕配。
- 舉個例子,比如api服務中我們知道一個token對應着一個用戶,就相當於web開發中的cookie和session,那么這會兒就可以拿token當作redis的key,然后將整個用戶數據當作value存儲到一個字典中
好了,總體來說今天這道題比較簡單比較入門!如果大家對redis這種五種數據結構的操作還不熟悉,那么你們一定要去熟悉一下!千萬不要懶惰,我說了這面試題是基礎入門的,對這五種數據操作幾乎是人人應該必備操作必會,連入門都不算。
今天算是用一道入門基礎題開刀,后面我會持續對redis進行更高門檻的面試題提問。如果今天這些題你有一半以上搞不定,說明你的基礎很差,趕緊補吧!
轉自:老李秀