技術分享——梳理下Redis五種數據類型和使用場景

寫在前面:2020年面試必備的Java後端進階面試題總結了一份複習指南在Github上,內容詳細,圖文並茂,有需要學習的朋友可以Star一下!
GitHub地址:https://github.com/abel-max/Java-Study-Note/tree/master

redis 五種數據類型和使用場景梳理!

Redis在我們日常工作中使用的非常頻繁,但是也有人只會使用string類型,那麼今天筆者梳理下redis中常用的5種數據類型,分別適用於哪些業務場景和基本操作,讓大家以後能夠在合適的緩存場景使用合適的數據類型。

String字符串類型

Redis支持的字符串類型不是定長分配的字符串,是動態變長字符串,修改字符串在沒有增加特別多內容的情況下不需要重新分配內存空間,內部結構實現上有點類似於java的ArrayList,採用預分配冗餘空間的方式來減少內存的頻繁分配。

常用使用場景

字符串類型常用的場景有以下這些:

(1)緩存結構體信息:

將結構體json序列化成字符串,然後將字符串保存在redis的value中,將結構體的業務唯一標示作爲key;這種保存json的用法用的最多的場景就是緩存用戶信息,將用戶bean信息轉成json再序列化爲字符串作爲value保存在redis中,將用戶id作爲key。從代碼中獲取用戶緩存信息就是一個逆過程,根據userid作爲key獲取到結構體json,然後將json轉成java bean。

基本操作:

127.0.0.1:6379> set user.10001 {“id”:”10001”,”name”:”monkey”}
(integer) 1

(2)計數功能:

我們都知道redis是單線程模式,並且redis將很多常用的事務操作進行了封裝,這裏我們最常用的就是數值自增或自減,redis的作者封裝了incr可以進行自增,沒調用一次自增1,因爲redis是單線程運行,所以就算client是多線程調用那麼也是正確自增,因爲incr命令中將read和write做了事務封裝。同樣可以設置incr的step,每次根據step進行自增,當然如果要達到自減的效果,那麼只要將step設置爲負數就可以了。

計數功能使用的場景很多,我們之前經常用在實時計數統計場景,也用在過庫存場景、限流計數場景等等,而且redis的性能也是非常高的,對於一般的併發量沒那麼高的系統都是適用的。

基本操作:

127.0.0.1:6379> set num 1
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> incrby num 2
(integer) 4

List列表類型

redis的列表的數據結構和Java中的LinkedList比較類似,所以List類型的前後插入和刪除速度是非常快的,但是隨機定位速度非常慢,時間複雜度是O(n)需要對列表進行遍歷。

常用使用場景

(1)list列表結構常用來做異步隊列使用

將需要延後處理的任務結構體序列化成字符串塞進 Redis 的列表,另一個線程從這個列表中輪詢數據進行處理。

(2)list可用於秒殺搶購場景

在商品秒殺場景最怕的就是商品超賣,爲了解決超賣問題,我們經常會將庫存商品緩存到類似MQ的隊列中,多線程的購買請求都是從隊列中取,取完了就賣完了,但是用MQ處理的化有點重,這裏就可以使用redis的list數據類型來實現,在秒殺前將本場秒殺的商品放到list中,因爲list的pop操作是原子性的,所以即使有多個用戶同時請求,也是依次pop,list空了pop拋出異常就代表商品賣完了。

基本操作:

//庫存爲3瓶可樂
> rpush goods:cola cola cola cola
(integer) 3
> lpop goods:cola
"cola"
> lpop goods:cola
"cola"

Hash數據類型

redis的hash相當於hashmap,內部實現上和hashmap一致,數組+鏈表的數據結構。

image.png

redis的hash數據類型只能是字符串。它們 rehash 的方式不一樣,因爲 Java 的 HashMap 在字典很大時,rehash 是個耗時的操作,需要一次性全部 rehash。Redis 爲了高性能,不能堵塞服務,所以採用了漸進式 rehash 策略。漸進式 rehash 會在 rehash 的同時,保留新舊兩個 hash 結構,查詢時會同時查詢兩個 hash 結構,然後在後續的定時任務中以及 hash 操作指令中,循序漸進地將舊 hash 的內容一點點遷移到新的 hash 結構中。當搬遷完成了,就會使用新的hash結構取而代之。 當 hash 移除了最後一個元素之後,該數據結構自動被刪除,內存被回收。

常用使用場景

(1)保存結構體信息

hash字典類型也是比較適合保存結構體信息的,不同於字符串一次序列化整個對象,hash可以對用戶結構中的每個字段單獨存儲。這樣當我們需要獲取結構體信息時可以進行部分獲取,而不用序列化所有字段,而將整個字符串保存的結構體信息只能一次性全部讀取。

基本操作:

127.0.0.1:6379> hset user.10002 name monkey
(integer) 1
127.0.0.1:6379> hget user.10002 name
"monkey"
127.0.0.1:6379> hgetall user.10002
1) "id"
2) "10002"
3) "name"
4) "monkey"

Set集合類型

redis的set相當於java中的HashSet,內部的健值是無序唯一的,相當於一個hashmap,但是value都是null。set數據類型其實沒什麼好講的,使用場景也是比較單一的,就是用在一些去重的場景裏,例如每個用戶只能參與一次活動、一個用戶只能中獎一次等等去重場景。

基本操作

127.0.0.1:6379> sadd userset 10001
(integer) 1
127.0.0.1:6379> sadd userset 10002
(integer) 1
127.0.0.1:6379> sadd userset 10001
(integer) 0
127.0.0.1:6379> sadd userset 10003 10004
(integer) 2
127.0.0.1:6379> smembers userset
1) "10001"
2) "10002"
3) "10003"
4) "10004"

Zset有序集合

它類似於 Java 的 SortedSet 和 HashMap 的結合體,一方面它是一個 set,保證了內部 value 的唯一性,另一方面它可以給每個 value 賦予一個 score,代表這個 value 的排序權重。zset內部是通過跳躍列表這種數據結構來實現的。因爲zset要支持隨機的插入和刪除,所以不能使用數組結構,而需要改成普通鏈表數據結構。zset需要根據score進行排序,所以每次插入或者刪除值都需要進行先在鏈表上查找定位。

常用使用場景

(1)各類熱門排序場景

例如熱門歌曲榜單列表,value值是歌曲ID,score是播放次數,這樣就可以對歌曲列表按播放次數進行排序。

當然還有類似微博粉絲列表、評論列表等等,可以將value定義爲用戶ID、評論ID,score定義爲關注時間、評論點贊次數等等。

基本操作:

這裏的例子就是對用戶的評分進行排序。

127.0.0.1:6379> zadd userzset 100 10002
(integer) 1
127.0.0.1:6379> zadd userzset 98 10001
(integer) 1
127.0.0.1:6379> zrange userzset 0 100
1) "10001"
2) "10002"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章