面試官:我們來聊一聊Redis吧,你瞭解多少就答多少

曠世奇才927發表於2022-03-13

哈嘍!大家好,我是小奇,一位不靠譜的程式設計師
小奇打算以輕鬆幽默的對話方式來分享一些技術,如果你覺得通過小奇的文章學到了東西,那就給小奇一個贊吧
文章持續更新,建議收藏關注

一、前言

作為一名Java程式設計師,Redis底層的一些原理是我們不必學會就可以搬磚工作的一種技能點,但是小奇為什麼還要講一下呢?難道就是為了浪費大家1分鐘的寶貴時間,一個人1分鐘,50萬人就是1年,5000萬人就是100年,賺了,小奇以一己之力成功搞掛一個人(血賺)。

當然不是,並且小奇的文章也沒有那麼多人看,最多也就浪費個吧。

學習Redis底層原理是因為面試官要問啊!,所以我們就要學,什麼?不實用的你不學?那鄰居小奇可要使勁學啦,到時候面試官只要小奇不要你。
在這裡插入圖片描述

至於你問為什麼面試官要問Redis底層原理呢,這個。。。我把這次機會留給你,下次你面試的時候面試官問:“講一下Redis底層原理”。你:“面試官你好,請問為什麼你要問Redis底層原理呢,你給我臺電腦,我五分鐘給你搭建好圖書管理系統他不香嗎,我們們鍵盤上見真章”。這時面試官就會告訴你答案,你就可以把答案打在評論區,讓小奇以及眾多小夥伴一起知道一下到底為什麼要問?


在這裡插入圖片描述

二、面試

在一個晴朗的週日,我來到了一個陌生的園區(別問為什麼是週日,問就是997,不過為了填飽肚子的打工人,只能明知山有虎、偏向虎山行),坐在陌生的會議室,等待HR小姐姐去叫面試官,此時我的心情和各位小夥伴一樣五味雜陳,擔心面試官問的會不會很難?問到我的知識盲區我該怎麼辦?一會自我介紹的時候要不要吹一下我和小奇的關係?

一位英俊瀟灑,眼神犀利的面試官走了進來,看到他那犀利、彷彿能看穿一切的眼神 ,我在想要不然一會就不要20k了,要8k得了,這個面試官一看就不好糊弄啊,但是我想起來我來之前剛看了小奇的趣學程式設計系列,我已經完全學會了小奇的精髓,我頓時就來了底氣,決定一會要30k,不給就學小奇賴著不走(哈哈)

面試官:小奇是吧,帶簡歷了嗎?

我:沒帶,現在彩印兩塊一張,我簡歷五張,每次面試都要花費十塊,我朋友說了還沒工作就先讓你掏錢的工作不要去。

面試官:。。。那你靠什麼來征服我,讓我錄用你

我:氣質?
請新增圖片描述

(此時面試官並沒有叫保安,而是從門後拿出了恭候我多時的棍子,我瞬間慫了)


在這裡插入圖片描述

我只好從我的雙肩包中拿出了我上午從其他公司面試官手中要回的簡歷,上午的情形是這樣的。


上午的面試官:今天的面試就到這吧,回去等通知吧!


我:面試官你好,如果貴公司不打算錄取我的話,能不能把我的紙質簡歷還給我,我下午還有一家面試。


上午的面試官:我說你的簡歷怎麼皺皺巴巴,原來你一直在迴圈利用啊!這個症狀出現多久了?


我:半拉月了。。。


(當我把皺皺巴巴的簡歷交給面試官後,這場面試才得以繼續進行。。。)

三、Redis基本資料型別與使用場景

面試官:我看你簡歷上寫的精通Redis?(哼,面試官輕蔑的一笑)

(看著面試官輕蔑的笑容,我忍不住拿出了我的Redis書籍推給了他)

我:這本書我倒背如流,你隨便提問,答不上來算我輸,答上來你就要為你的輕蔑向我道歉。


在這裡插入圖片描述

(我的笑容逐漸自信。。。)


在這裡插入圖片描述

(此時面試官看著書若有所思,我懷疑他肯定在想他對這本書的瞭解程度吧)

面試官:好吧,那先簡單說一下Redis有哪些資料型別吧

我:redis主要有五種資料型別,分別是String、Hash、List、Set、ZSet

面試官:那他們都是怎麼儲存和讀取資料的呢,有哪些使用場景呢?

1、String

單值儲存:set [key] [value]
在這裡插入圖片描述
取值:get [key]
在這裡插入圖片描述

多值儲存:mset [key1] [value] [key2] [value]
在這裡插入圖片描述
取值:mget [key1] [key2]
在這裡插入圖片描述

分散式鎖上鎖:setnx [key] true


返回1代表上鎖成功
在這裡插入圖片描述
返回0代表上鎖失敗
在這裡插入圖片描述
分散式鎖釋放鎖:del [key]
在這裡插入圖片描述
設定超時時間:expire [key] [時間] (如果出現異常導致刪除鎖失敗,可以設定超時時間,到達時間鎖自動刪除)
在這裡插入圖片描述
實現原子性分散式鎖加鎖並設定超時時間:set [key] true ex [時間] nx (如果上完鎖在給鎖設定超時時間之間出現異常,還是會導致鎖無法刪除,那麼將上鎖命令和設定超時時間命令合為一個命令)
在這裡插入圖片描述

計數器:incr [key]
在這裡插入圖片描述
獲取計數器的值:get [key]
在這裡插入圖片描述
批量獲取計數:incrby [key]
在這裡插入圖片描述
獲取計數器的值:get [key]
在這裡插入圖片描述

2、Hash

儲存資料:hset [table] [key] [value] (這裡我們可以假設實現向購物車中新增商品)


向購物車新增一個蘋果
在這裡插入圖片描述
向購物車新增一本書
在這裡插入圖片描述
向購物車新增一個香蕉
在這裡插入圖片描述

在原有商品上加數量:hincrby [table] [key] [數量]


再向購物車中新增一個蘋果
在這裡插入圖片描述

商品種類數量:hlen [table]
在這裡插入圖片描述

獲取購物車所有的商品:hgetall [table]
在這裡插入圖片描述

刪除商品:hdel [table] [key]
在這裡插入圖片描述

3、List

將一個值放入列表的頭部(最左邊):lpush [key] [value]
在這裡插入圖片描述

移除並返回列表的頭元素:lpop [key]
在這裡插入圖片描述

將一個值放入列表的尾部(最右邊):rpush [key] [value]
在這裡插入圖片描述

移除並返回列表的尾元素:rpop [key]
在這裡插入圖片描述

返回列表中指定區間內的元素:lrange [key] [開始位置] [結束位置]
在這裡插入圖片描述

從列表表頭彈出一個元素,若列表中沒有元素,阻塞等待time秒,如果time=0,一直阻塞等待
在這裡插入圖片描述
從列表表尾彈出一個元素,若列表中沒有元素,阻塞等待time秒,如果time=0,一直阻塞等待
在這裡插入圖片描述

4、Set

往集合key中存入元素,元素存在則忽略,若key不存在則新建:sadd [key] [元素] (這裡我們模仿一個抽獎的業務場景,先往集合中放入要抽獎的人)
在這裡插入圖片描述

從集合key中隨機選取幾個元素,元素不從集合中刪除:srandmember [key] [元素個數] (這裡我們抽兩個獎項)
在這裡插入圖片描述

獲取集合key中所有元素:smembers [key]
在這裡插入圖片描述

獲取集合key中元素的個數:scard [key]
在這裡插入圖片描述

判斷一元素是否存在於集合中:sismember [key] [元素]
在這裡插入圖片描述

從集合中刪除元素:srem [key] [元素]
在這裡插入圖片描述

從集合中隨機選出幾個元素,並且刪除:spop [key] [元素個數] (例如我們抽獎的時候先抽了三等獎,那麼抽二等獎的時候三等獎的人就沒有資格了,就要將三等獎的人刪除)
在這裡插入圖片描述

交集運算:sinter [key] [元素]
在這裡插入圖片描述

將交集結果存入新集合key2中:sinterstore [key2] [key] [元素]
在這裡插入圖片描述

並集運算:sunion [key] [元素]
在這裡插入圖片描述

將並集結果存入新集合key2中:sunionstore [key2] key [元素]
在這裡插入圖片描述

差集運算:sdiff [key] [運算]
在這裡插入圖片描述

將差集結果存入新集合key2中:sdiffstore [key2] [key] [元素]
在這裡插入圖片描述

5、ZSet

往有序集合key中加入帶分值的元素:zadd [key] [分值] [元素] (業務中我們可以用來實現例如微博熱搜排行的功能)
在這裡插入圖片描述

返回有序集合key中元素的分值:zscore [key] [元素]
在這裡插入圖片描述

返回有序集合key中元素的個數:zcard [key]
在這裡插入圖片描述

為有序集合key中元素的分值加上一個分值:zincrby [key] [分值] [元素]
在這裡插入圖片描述

正序獲取有序集合key從開始下標到結束下標的元素:zrange [key] [開始] [結束]
在這裡插入圖片描述

倒敘獲取有序集合key從開始下標到結束下標的元素:zrevrange [key] [開始下標] [結束下標] (這裡就是例如微博熱搜榜中根據熱度倒敘排序獲取前十個)
在這裡插入圖片描述

從有序集合key中刪除元素:zrem [key] [元素]
在這裡插入圖片描述

(整理不易,性感小奇線上求贊。。。)


在這裡插入圖片描述

四、Redis日常問題

面試官:嗯。你上面寫了那麼多我也顧不上看,簡單的問你幾個問題吧

我:好

面試官:Redis中我們怎麼建立分散式鎖

我:使用setnx命令

面試官:Redis中建立分散式鎖後出現異常解鎖失敗,怎麼將這個鎖刪掉

我:可以使用expire來給鎖加一個時間,過了這個時間後Redis自動將這個鎖刪掉。

面試官:如果在加時間之前就出現異常了,時間沒有加上怎麼辦?

我:可以使用原子性的命令將分散式鎖和時間一同建立出來,這樣就不用擔心異常了,因為原子性,一個成功都成功,一個失敗都失敗。

在這裡插入圖片描述

面試官:Redis是單執行緒的嗎?

我:Redis在讀寫操作的時候是單執行緒的,但是其它功能,例如持久化、非同步刪除、叢集資料同步等是有額外的執行緒執行的。

面試官:Redis單執行緒為什麼還能這麼快?

我:因為Redis的資料都在記憶體中,而且單執行緒避免了多執行緒的切換效能損耗問題。

面試官:Redis單執行緒如何處理併發客戶端連線?

我:Redis利用epoll來實現IO多路複用,將連線資訊和事件放到佇列中,依次放到檔案事件分派器中,事件分派器將事件分發給事件處理器。

在這裡插入圖片描述

面試官:我想全量查詢Redis中所有key怎麼查詢,或者模糊查詢符合規則的key怎麼查詢呢

我:使用 keys * 可以查詢Redis中所有的key,如果要模糊查詢直接加上規則即可,例如要查詢字首為小奇的key可以使用 keys 小奇* 來查詢

面試官:這樣查詢有沒有什麼問題呢,有沒有其他的解決方案呢?

我:使用 keys * 查詢是全量查詢Redis中的key值,如果key值過多的話最造成執行緒堵塞,因為Redis讀寫是單執行緒的,我們可以使用scan命令漸進式讀取資料。

面試官:可以詳細說一下scan命令嗎?

我:scan命令的格式為:scan [遊標] match [萬用字元] count [每一次查詢的數量] (初始查詢的時候遊標為0,然後第二次查詢遊標為第一次查詢時返回的資料,依次類推,最後遊標返回0時表示查詢完畢)


我現在Redis中一共有9條資料,我每次查詢3條,分三次查詢完畢。
在這裡插入圖片描述

面試官:scan命令有什麼缺點嗎,一定能夠完全獲取全量的資料嗎?

我:不一定,如果在scan的過程中有新的資料變化,例如插入資料,刪除資料等,那麼新增的鍵可能沒有遍歷到,因為scan遍歷過的地方就不在遍歷了,你插入到遍歷過的地方就不會再遍歷到。

在這裡插入圖片描述

面試官:小夥子真厲害啊,我這邊沒有什麼要問的了,你還有什麼問題要問(面試官兩眼放光)

我:額。。。面試官這個我的紙質簡歷可以給我嗎,可以不往我的簡歷上寫寫畫畫嗎,我明天的面試還要用。

面試官:還面啥別的公司啊,就來我這吧,條件隨便開

我:那就100k吧(此時面試官又拿起了他準備好的棍子)

面試官:你要是不來就給我推薦一下,讓別人來我這面試一下

我:你先好好學習一下Redis吧,今天幸虧只是我來了,如果是小奇的忠實讀者來了,你將會被虐的很慘的。(我將我的《Redis設計與實現》留給了面試官,轉身留下了帥氣的背影,而面試官落寞無神的呆呆的坐在那裡,彷彿一個億離他而去。。。)

五、總結

這裡關於Redis還沒有整理完畢,文章後面持續更新,建議收藏。

文章中涉及到的命令大家一定要像我一樣每個都敲幾遍,只有在敲的過程中才能發現自己對命令是否真正的掌握了。

如果覺得我的文章還不錯的話就點個贊吧。

相關文章