離譜!面試為啥都問Redis?趕緊補(bǔ)一下
大家好,我是哪吒。
一、同樣是緩存,用map不行嗎?
(1)Redis可以存儲(chǔ)幾十個(gè)G的數(shù)據(jù),Map行嗎?
(2)Redis的緩存可以進(jìn)行本地持久化,Map行嗎?
(3)Redis可以作為分布式緩存,Map只能在同一個(gè)JVM中進(jìn)行緩存;
(4)Redis支持每秒百萬級(jí)的并發(fā),Map行嗎?
(5)Redis有過期機(jī)制,Map有嗎?
(6)Redis有豐富的API,支持非常多的應(yīng)用場景,Map行嗎?
二、Redis為什么是單線程的?
(1)代碼更清晰,處理邏輯更簡單。
(2)不用考慮各種鎖的問題,不存在加鎖和釋放鎖的操作,沒有因?yàn)榭赡艹霈F(xiàn)死鎖而導(dǎo)致的性能問題。
(3)不存在多線程切換而消耗CPU。
(4)無法發(fā)揮多核CPU的優(yōu)勢(shì),但可以采用多開幾個(gè)Redis實(shí)例來完善。
三、Redis真的是單線程的嗎?
(1)Redis6.0之前是單線程的,Redis6.0之后開始支持多線程。
(2)Redis內(nèi)部使用了基于epoll的多路復(fù)用,也可以多部署幾個(gè)Redis服務(wù)器解決單線程的問題。
(3)Redis主要的性能瓶頸是內(nèi)存和網(wǎng)絡(luò)。
(4)內(nèi)存好說,加內(nèi)存條就行了,而網(wǎng)絡(luò)才是大麻煩,所以Redis6內(nèi)存好說,加內(nèi)存條就行了。
(5)而網(wǎng)絡(luò)才是大麻煩,所以Redis6.0引入了多線程的概念。
(6)Redis6.0在網(wǎng)絡(luò)IO處理方面引入了多線程,如網(wǎng)絡(luò)數(shù)據(jù)的讀寫和協(xié)議解析等,需要注意的是,執(zhí)行命令的核心模塊還是單線程的。
四、Redis優(yōu)缺點(diǎn)
1、優(yōu)點(diǎn)
(1)Redis是KV數(shù)據(jù)庫,MySQL是關(guān)系型數(shù)據(jù)庫,Redis速度更快。
(2)Redis數(shù)據(jù)操作主要在內(nèi)存中,MySQL主要將數(shù)據(jù)存儲(chǔ)在硬盤,Redis速度更快。
(3)Redis同樣支持持久化(RDB+AOF),Redis支持將數(shù)據(jù)異步將內(nèi)存的數(shù)據(jù)持久化到硬盤上,避免Redis宕機(jī)出現(xiàn)數(shù)據(jù)丟失的問題。
(4)Redis性能極高,讀的速度是110000次/秒,寫的速度是81000次/秒。
(5)Redis數(shù)據(jù)類型豐富,不僅支持KV鍵值對(duì),還支持list、set、zset、hash等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)。
(6)Redis支持?jǐn)?shù)據(jù)的備份,即master-slave模式的數(shù)據(jù)備份。
(7)Redis支持簡單的事務(wù),操作滿足原子性。
(8)Redis支持讀寫分離,分擔(dān)讀的壓力。
(9)Redis支持哨兵模式,實(shí)現(xiàn)故障的自動(dòng)轉(zhuǎn)移。
(10)單線程操作,避免了頻繁的上下文切換。
(11)采用了非阻塞I/O多路復(fù)用機(jī)制,性能卓越。
2、缺點(diǎn)
(1)數(shù)據(jù)存儲(chǔ)在內(nèi)存,容易造成數(shù)據(jù)丟失。
(2)存儲(chǔ)容量受內(nèi)存的限制,只能存儲(chǔ)少量的常用數(shù)據(jù)。
(3)緩存和數(shù)據(jù)庫雙寫一致性問題。
(4)用于緩存時(shí),容易出現(xiàn)內(nèi)存穿透、緩存擊穿、緩存雪崩的問題。
(5)修改配置文件后,需要進(jìn)行重啟,將硬盤中的數(shù)據(jù)同步到內(nèi)存中,消耗的時(shí)間較長,而且數(shù)據(jù)同步的時(shí)間里Redis不能提供服務(wù)。
五、Redis常見業(yè)務(wù)場景
(1)Redis是基于內(nèi)存的nosql數(shù)據(jù)庫,可以通過新建線程的形式進(jìn)行持久化,不影響Redis單線程的讀寫操作。
(2)通過list取最新的N條數(shù)據(jù)。
(3)模擬類似于token這種需要設(shè)置過期時(shí)間的場景。
(4)發(fā)布訂閱消息系統(tǒng)。
(5)定時(shí)器、計(jì)數(shù)器。
(6)緩存加速、分布式會(huì)話、排行榜、分布式計(jì)數(shù)器、分布式鎖。
(7)Redis支持事務(wù)、持久化、LUA腳本、發(fā)布/訂閱、緩存淘汰、流技術(shù)等特性。
六、Redis常見數(shù)據(jù)類型
1、String
(1)String簡介
String 是最基本的 key-value 結(jié)構(gòu),key 是唯一標(biāo)識(shí),value 是具體的值,value其實(shí)不僅是字符串, 也可以是數(shù)字(整數(shù)或浮點(diǎn)數(shù)),value 最多可以容納的數(shù)據(jù)長度是 512M。
(2)應(yīng)用場景
① 作為緩存數(shù)據(jù)庫
在Java管理系統(tǒng)體系中,大多數(shù)都是用MySQL存儲(chǔ)數(shù)據(jù),redis作為緩存,因?yàn)镽edis具有支撐高并發(fā)的特性,通常能起到加速讀寫和降低數(shù)據(jù)庫服務(wù)器壓力的作用,大多數(shù)請(qǐng)求都會(huì)先請(qǐng)求Redis,如果Redis中沒有數(shù)據(jù),再請(qǐng)求MySQL數(shù)據(jù)庫,然后再緩存到Redis中,以備下次使用。
② 計(jì)數(shù)器
Redis字符串中有一個(gè)命令I(lǐng)NCR key,incr命令會(huì)對(duì)值進(jìn)行自增操作,比如CSDN的文章閱讀,視頻的播放量,都可以通過Redis來計(jì)數(shù),每閱讀一次就+1,同時(shí)將這些數(shù)據(jù)異步存儲(chǔ)到MySQL數(shù)據(jù)庫中,降低MySQL服務(wù)器的寫入壓力。
③ 共享session
在分布式系統(tǒng)中,用戶每次請(qǐng)求一般會(huì)訪問不同的服務(wù)器 ,這就會(huì)導(dǎo)致session不同步的問題,這時(shí),一般會(huì)使用Redis來解決這個(gè)問題,將session存入Redis,使用的時(shí)候從Redis中取出就可以了。
④ 分布式鎖
- setnx key value,加鎖
- del key,釋放鎖
(3)key操作命令
(4)set key value
SET key value [NX | XX] [GET] [EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL]。
- EX seconds,設(shè)置過期時(shí)間,單位秒。
- PX milliseconds,設(shè)置過期時(shí)間,單位毫秒。
- EXAT timestamp-seconds,設(shè)置過期時(shí)間,以秒為單位的UNIX時(shí)間戳。
- PXAT timestamp-milliseconds,設(shè)置過期時(shí)間,以毫秒為單位的UNIX時(shí)間戳。
- NX,鍵不存在的時(shí)候設(shè)置鍵值。
- XX,鍵存在的時(shí)候設(shè)置鍵值。
- KEEPTTL,保留設(shè)置前指定鍵的生存時(shí)間。
- GET,返回指定鍵原本的值,若鍵不存在返回nil。
備注:
命令不區(qū)分大小寫,而key是區(qū)分大小寫的。
help @類型:查看當(dāng)前類型相關(guān)的操作命令。
Since the SET command options can replace SETNX, SETEX, PSETEX, GETSET, it is possible that in future versions of Redis these commands will be deprecated and finally removed。
(5)同時(shí)設(shè)置多個(gè)鍵值
(6)獲取指定區(qū)間范圍內(nèi)的值
getrange、setrange。
(7)數(shù)值增減
- INCR key,遞增數(shù)字。
- INCRBY key increment,增加指定的數(shù)值遞增。
- DECR key,遞減數(shù)值。
- DECRBY key decrement,指定指定的數(shù)值遞減。
(8)獲取字符串的長度,內(nèi)容追加
- STRLEN key,獲取值的長度。
- APPEND key value,內(nèi)容追加。
2、List
(1)List 列表簡介
List 列表是簡單的字符串列表,按照插入順序排序,可以從頭部或尾部向 List 列表添加元素。
列表的最大長度為 2^32 - 1,也即每個(gè)列表支持超過 40 億個(gè)元素。
主要功能有push/pop,一般用在棧、隊(duì)列、消息隊(duì)列等場景。
- left、right都可以插入添加。
- 如果鍵不存在,創(chuàng)建新的鏈表。
- 如果鍵存在,新增內(nèi)容。
- 如果值全部移除,對(duì)應(yīng)的鍵也會(huì)消失。
它的底層是雙向鏈表,對(duì)兩端的操作性能很高,通過索引下標(biāo)操作中間的節(jié)點(diǎn),性能會(huì)較差。
(2)應(yīng)用場景
① 消息隊(duì)列
使用 lpush + rpop或者 rpush + lpop實(shí)現(xiàn)消息隊(duì)列,Redis還支持阻塞操作,在彈出元素的時(shí)候使用阻塞命令來實(shí)現(xiàn)阻塞隊(duì)列。
② 作為棧使用
使用 lpush+lpop或者 rpush+rpop實(shí)現(xiàn)棧。
③ 文章列表
(3)常用命令
3、Hash
(1)hash簡介
Hash 是一個(gè)鍵值對(duì)(key - value)集合,value也是一個(gè)hash,相當(dāng)于 Map<String,Map<Object,Object>>。
(2)常用場景
由于特殊的數(shù)據(jù)結(jié)構(gòu),hash一般作為存儲(chǔ)bean使用,String+JSON的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)特定的應(yīng)用場景。
(3)常用命令
4、Set
(1)Set類型簡介
Set 類型是一個(gè)無序并唯一的鍵值集合,它的存儲(chǔ)順序不會(huì)按照插入的先后順序進(jìn)行存儲(chǔ)。
一個(gè)集合最多可以存儲(chǔ) 2^32-1 個(gè)元素。概念和數(shù)學(xué)中個(gè)的集合基本類似,可以交集,并集,差集等等,所以 Set 類型除了支持集合內(nèi)的增刪改查,同時(shí)還支持多個(gè)集合取交集、并集、差集。
(2)應(yīng)用場景
① 相同好友可見
在朋友圈場景中,對(duì)于點(diǎn)贊、評(píng)論的功能,通過交集實(shí)現(xiàn)相同還有可見的功能。
② 共同關(guān)注、共同喜好
③ 抽獎(jiǎng)功能
(3)常用命令
5、Zset
(1)Zset 類型簡介
Zset 類型(有序集合類型)相比于 Set 類型多了一個(gè)排序?qū)傩?score(分值),對(duì)于有序集合 ZSet 來說,每個(gè)存儲(chǔ)元素相當(dāng)于有兩個(gè)值組成的,一個(gè)是有序結(jié)合的元素值,一個(gè)是排序值。
有序集合保留了集合不能有重復(fù)成員的特性(分值可以重復(fù)),但不同的是,有序集合中的元素可以排序。
zset k1 score1 v1 score2 v2。
(2)應(yīng)用場景
① 排行榜
通過score來記錄點(diǎn)贊數(shù),然后根據(jù)score進(jìn)行排序,實(shí)現(xiàn)排行榜的功能。
② 延遲消息隊(duì)列
訂單系統(tǒng),下單后需要在15分鐘內(nèi)進(jìn)行支付操作,否則自動(dòng)取消訂單。
將下單后15分鐘后的時(shí)間作為score,訂單作為value存入Redis,消費(fèi)者輪詢?nèi)ハM(fèi),如果消費(fèi)的大于等于score,則取消該訂單。
(3)Zset常用命令
6、BitMap
(1)Bitmap簡介
Bitmap,即位圖,是一串連續(xù)的二進(jìn)制數(shù)組(0和1),可以通過偏移量(offset)定位元素。BitMap通過最小的單位bit來進(jìn)行0|1的設(shè)置,表示某個(gè)元素的值或者狀態(tài),時(shí)間復(fù)雜度為O(1)。
(2)應(yīng)用場景
由于 bit 是計(jì)算機(jī)中最小的單位,使用它進(jìn)行儲(chǔ)存將非常節(jié)省空間,特別適合一些數(shù)據(jù)量大且使用二值統(tǒng)計(jì)的場景。
① 簽到統(tǒng)計(jì)
② 判斷用戶是否登錄
③ 統(tǒng)計(jì)連續(xù)學(xué)習(xí)打卡的人
(3)BitMap常用命令
7、BitField
通過bitfield命令可以一次性操作多個(gè)比特位,它會(huì)執(zhí)行一系列操作并返回一個(gè)響應(yīng)數(shù)組,這個(gè)數(shù)組中的元素對(duì)參數(shù)列表中的相應(yīng)操作的執(zhí)行結(jié)果。
8、HyperLogLog
(1)HyperLogLog簡介
Redis HyperLogLog 是 Redis 2.8.9 版本新增的數(shù)據(jù)類型,是一種用于「統(tǒng)計(jì)基數(shù)」的數(shù)據(jù)集合類型,基數(shù)統(tǒng)計(jì)就是指統(tǒng)計(jì)一個(gè)集合中不重復(fù)的元素個(gè)數(shù)。但要注意,HyperLogLog 是統(tǒng)計(jì)規(guī)則是基于概率完成的,不是非常準(zhǔn)確,標(biāo)準(zhǔn)誤算率是 0.81%。
所以,簡單來說 HyperLogLog 提供不精確的去重計(jì)數(shù)。
HyperLogLog 的優(yōu)點(diǎn)是,在輸入元素的數(shù)量或者體積非常非常大時(shí),計(jì)算基數(shù)所需的內(nèi)存空間總是固定的、并且是很小的。
在 Redis 里面,每個(gè) HyperLogLog 鍵只需要花費(fèi) 12 KB 內(nèi)存,就可以計(jì)算接近 2^64 個(gè)不同元素的基數(shù),和元素越多就越耗費(fèi)內(nèi)存的 Set 和 Hash 類型相比,HyperLogLog 就非常節(jié)省空間。
(2)應(yīng)用場景
百萬級(jí)網(wǎng)頁 UV 計(jì)數(shù)
(3)常用命令
- pfadd key element,添加元素
- pfcount key,返回指定HyperLogLog的基數(shù)的估算值;
- pfmerge destkey sourcekey,將多個(gè)HyperLogLog合并成一個(gè)HyperLogLog;
9、GEO
(1)GEO簡介
Redis GEO 是 Redis 3.2 版本新增的數(shù)據(jù)類型,主要用于存儲(chǔ)地理位置信息,并對(duì)存儲(chǔ)的信息進(jìn)行操作。
在日常生活中,我們?cè)絹碓揭蕾囁阉鳌案浇牟宛^”、在打車軟件上叫車,這些都離不開基于位置信息服務(wù)(Location-Based Service,LBS)的應(yīng)用。LBS 應(yīng)用訪問的數(shù)據(jù)是和人或物關(guān)聯(lián)的一組經(jīng)緯度信息,而且要能查詢相鄰的經(jīng)緯度范圍,GEO 就非常適合應(yīng)用在 LBS 服務(wù)的場景中。
(2)應(yīng)用場景
高德地圖、滴滴打車等定位軟件。
(3)常用命令
10、Stream
(1)Stream簡介
Redis Stream 是 Redis 5.0 版本新增加的數(shù)據(jù)類型,Redis 專門為消息隊(duì)列設(shè)計(jì)的數(shù)據(jù)類型。
在 Redis 5.0 Stream 沒出來之前,消息隊(duì)列的實(shí)現(xiàn)方式都有著各自的缺陷,例如:
- 發(fā)布訂閱模式,不能持久化也就無法可靠的保存消息,并且對(duì)于離線重連的客戶端不能讀取歷史消息的缺陷。
- List 實(shí)現(xiàn)消息隊(duì)列的方式不能重復(fù)消費(fèi),一個(gè)消息消費(fèi)完就會(huì)被刪除,而且生產(chǎn)者需要自行實(shí)現(xiàn)全局唯一 ID。
基于以上問題,Redis 5.0 便推出了 Stream 類型也是此版本最重要的功能,用于完美地實(shí)現(xiàn)消息隊(duì)列,它支持消息的持久化、支持自動(dòng)生成全局唯一 ID、支持 ack 確認(rèn)消息的模式、支持消費(fèi)組模式等,讓消息隊(duì)列更加的穩(wěn)定和可靠。
(2)應(yīng)用場景
消息隊(duì)列
(3)常用命令
七、總結(jié)
Redis是一個(gè)key-value存儲(chǔ)系統(tǒng),支持10種數(shù)據(jù)類型,總結(jié)了為何要用Redis替代map作為程序緩存、Redis為什么是單線程的、Redis的優(yōu)缺點(diǎn)、Redis的常用場景,做了一次Redis的快速入門。
本文轉(zhuǎn)載自微信公眾號(hào)「哪吒編程」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系哪吒編程公眾號(hào)。