Redis資料型別大全:“5種基礎”資料型別+“3種特殊”資料型別

一、“5種基礎”資料型別

Redis 有望所有的key(鍵)都是字串。我們在談基礎資料結構時,討論的是儲存值的資料型別,主要包括常見的5種資料型別,分別是:String、List、Set、Zset、Hash

Redis資料型別大全:“5種基礎”資料型別+“3種特殊”資料型別

1。1 Redis資料結構簡介

Redis基礎文章非常多,關於基礎資料結構型別,我推薦你先看下官方網站內容 (opens new window),然後再看下面的小結

首先對redis來說,所有的key(鍵)都是字串。我們在談基礎資料結構時,討論的是儲存值的資料型別,主要包括常見的5種資料型別,分別是:String、List、Set、Zset、Hash。

Redis資料型別大全:“5種基礎”資料型別+“3種特殊”資料型別

Redis資料型別大全:“5種基礎”資料型別+“3種特殊”資料型別

1。2 基礎資料結構詳解

內容其實比較簡單,我覺得理解的重點在於這個結構怎麼用,能夠用來做什麼?所以我在梳理時,圍繞圖例,命令,執行和場景來闡述

1。2。1 String字串

String是redis中最基本的資料型別,一個key對應一個value。

String型別是二進位制安全的,意思是 redis 的 string 可以包含任何資料。如數字,字串,jpg圖片或者序列化的物件。

圖例

下圖是一個String型別的例項,其中鍵為hello,值為world

Redis資料型別大全:“5種基礎”資料型別+“3種特殊”資料型別

命令使用

Redis資料型別大全:“5種基礎”資料型別+“3種特殊”資料型別

命令執行

127。0。0。1

6379

>

set

hello

world

OK

127。0。0。1

6379

>

get

hello

“world”

127。0。0。1

6379

>

del

hello

integer

1

127。0。0。1

6379

>

get

hello

nil

127。0。0。1

6379

>

get

counter

“2”

127。0。0。1

6379

>

incr

counter

integer

3

127。0。0。1

6379

>

get

counter

“3”

127。0。0。1

6379

>

incrby

counter

100

integer

103

127。0。0。1

6379

>

get

counter

“103”

127。0。0。1

6379

>

decr

counter

integer

102

127。0。0。1

6379

>

get

counter

“102”

實戰場景

快取

: 經典使用場景,把常用資訊,字串,圖片或者影片等資訊放到redis中,redis作為快取層,mysql做持久化層,降低mysql的讀寫壓力。

計數器

:redis是單執行緒模型,一個命令執行完才會執行下一個,同時資料可以一步落地到其他的資料來源。

session

:常見方案spring session + redis實現session共享

1。2。2 List列表

Redis中的List其實就是連結串列(Redis用雙端連結串列實現List)。

使用List結構,我們可以輕鬆地實現最新訊息排隊功能(比如新浪微博的TimeLine)。List的另一個應用就是訊息佇列,可以利用List的 PUSH 操作,將任務存放在List中,然後工作執行緒再用 POP 操作將任務取出進行執行。

圖例

Redis資料型別大全:“5種基礎”資料型別+“3種特殊”資料型別

命令使用

Redis資料型別大全:“5種基礎”資料型別+“3種特殊”資料型別

使用列表的技巧

lpush+lpop=Stack(棧)

lpush+rpop=Queue(佇列)

lpush+ltrim=Capped Collection(有限集合)

lpush+brpop=Message Queue(訊息佇列)

命令執行

127。0。0。1

6379

>

lpush

mylist

1

2

ll

ls

mem

integer

5

127。0。0。1

6379

>

lrange

mylist

0

-1

1

“mem”

2

“ls”

3

“ll”

4

5

“1”

127。0。0。1

6379

>

lindex

mylist

-1

127。0。0。1

6379

>

lindex

mylist

10

#

index

不在

mylist

的區間範圍內

nil

實戰場景微博

TimeLine

: 有人釋出微博,用lpush加入時間軸,展示新的列表資訊。

訊息佇列

1。2。3 Set集合

Redis 的 Set 是 String 型別的無序集合。集合成員是唯一的,這就意味著集合中不能出現重複的資料。

Redis 中集合是透過雜湊表實現的,所以新增,刪除,查詢的複雜度都是 O(1)。

圖例

Redis資料型別大全:“5種基礎”資料型別+“3種特殊”資料型別

命令使用

Redis資料型別大全:“5種基礎”資料型別+“3種特殊”資料型別

命令執行

127。0。0。1

6379

>

sadd

myset

hao

hao1

xiaohao

hao

integer

3

127。0。0。1

6379

>

smember

myset

1

“xiaohao”

2

“hao1”

3

“hao”

127。0。0。1

6379

>

sismember

myset

hao

integer

1

實戰場景

標籤

(tag),給使用者新增標籤,或者使用者給訊息新增標籤,這樣有同一標籤或者類似標籤的可以給推薦關注的事或者關注的人。

點贊,或點踩,收藏等

,可以放到set中實現

1。2。4 Hash雜湊

Redis hash 是一個 string 型別的 field(欄位) 和 value(值) 的對映表,hash 特別適合用於儲存物件。

圖例

Redis資料型別大全:“5種基礎”資料型別+“3種特殊”資料型別

命令使用

Redis資料型別大全:“5種基礎”資料型別+“3種特殊”資料型別

命令執行

127。0

0

1

6379

>

hset

user

name1

hao

integer

1

127。0

0

1

6379

>

hset

user

email1

hao

@

163

com

integer

1

127。0

0

1

6379

>

hgetall

user

1

“name1”

2

3

“email1”

4

“hao@163。com”

127。0

0

1

6379

>

hget

user

user

nil

127。0

0

1

6379

>

hget

user

name1

127。0

0

1

6379

>

hset

user

name2

xiaohao

integer

1

127。0

0

1

6379

>

hset

user

email2

xiaohao

@

163

com

integer

1

127。0

0

1

6379

>

hgetall

user

1

2

3

4

5

“name2”

6

7

“email2”

8

“xiaohao@163。com”

實戰場景

快取

: 能直觀,相比string更節省空間,的維護快取資訊,如用

資訊,影片資訊等

1。2。5 Zset有序集合

Redis 有序集合和集合一樣也是 string 型別元素的集合,且不允許重複的成員。不同的是每個元素都會關聯一個 double 型別的分數。redis 正是透過分數來為集合中的成員進行從小到大的排序。

有序集合的成員是唯一的,但分數(score)卻可以重複。集合是透過雜湊表實現的,所以新增,刪除,查詢的複雜度都是 O(1)。

圖例

Redis資料型別大全:“5種基礎”資料型別+“3種特殊”資料型別

命令使用

127。0。0。1

6379

>

zadd

myscoreset

100

hao

90

xiaohao

integer

2

127。0。0。1

6379

>

ZRANGE

myscoreset

0

-1

1

2

127。0。0。1

6379

>

ZSCORE

myscoreset

hao

“100”

實戰場景

排行榜

:有序集合經典使用場景。例如小說影片等網站需要對使用者上傳的小說影片做排行榜,榜單可以按照使用者關注數,更新時間,字數等打分,做排行

二、3種特殊型別詳解

Redis除了上文中5種基礎資料型別,還有三種特殊的資料型別,分別是 HyperLogLogs(基數統計), Bitmaps (點陣圖) 和 geospatial (地理位置)

2。1 HyperLogLogs(基數統計)

Redis 2。8。9 版本更新了 Hyperloglog 資料結構!

什麼是基數?

舉個例子,A = {1, 2, 3, 4, 5}, B = {3, 5, 6, 7, 9};那麼基數(不重複的元素)= 1, 2, 4, 6, 7, 9; (允許容錯,即可以接受一定誤差)

HyperLogLogs 基數統計用來解決什麼問題

這個結構可以非常省記憶體的去統計各種計數,比如註冊 IP 數、每日訪問 IP 數的頁面實時UV、線上使用者數,共同好友數等。

它的優勢體現在哪

一個大型的網站,每天 IP 比如有 100 萬,粗算一個 IP 消耗 15 位元組,那麼 100 萬個 IP 就是 15M。而 HyperLogLog 在 Redis 中每個鍵佔用的內容都是 12K,理論儲存近似接近 2^64 個值,不管儲存的內容是什麼,它一個基於基數估算的演算法,只能比較準確的估算出基數,可以使用少量固定的記憶體去儲存並識別集合中的的唯一元素。而且這個估算的基數並不一定準確,是一個帶有 0。81% 標準錯誤的近似值(對於可以接受一定容錯的業務場景,比如IP數統計,UV等,是可以忽略不計的)。

相關命令使用

127。0。0。1

6379

>

pfadd

key1

a

b

c

d

e

f

g

h

i

#

建立第一組元素

integer

1

127。0。0。1

6379

>

pfcount

key1

#

統計元素的基數數量

integer

9

127。0。0。1

6379

>

pfadd

key2

c

j

k

l

m

e

g

a

#

建立第二組元素

integer

1

127。0。0。1

6379

>

pfcount

key2

integer

8

127。0。0。1

6379

>

pfmerge

key3

key1

key2

#

合併兩組:

key1

key2

-

>

key3

並集

OK

127。0。0。1

6379

>

pfcount

key3

integer

13

2。2 Bitmap (位儲存)

Bitmap 即點陣圖資料結構,都是操作二進位制位來進行記錄,只有0 和 1 兩個狀態。

用來解決什麼問題

比如:統計使用者資訊,活躍,不活躍! 登入,未登入! 打卡,不打卡!

兩個狀態的,都可以使用 Bitmaps

如果儲存一年的打卡狀態需要多少記憶體呢? 365 天 = 365 bit 1位元組 = 8bit 46 個位元組左右!

相關命令使用

使用bitmap 來記錄 週一到週日的打卡! 週一:1 週二:0 週三:0 週四:1 ……

127。0。0。1

6379

>

setbit

sign

0

1

integer

0

127。0。0。1

6379

>

setbit

sign

1

1

integer

0

127。0。0。1

6379

>

setbit

sign

2

0

integer

0

127。0。0。1

6379

>

setbit

sign

3

1

integer

0

127。0。0。1

6379

>

setbit

sign

4

0

integer

0

127。0。0。1

6379

>

setbit

sign

5

0

integer

0

127。0。0。1

6379

>

setbit

sign

6

1

integer

0

檢視某一天是否有打卡!

127。0。0。1

6379

>

getbit

sign

3

integer

1

127。0。0。1

6379

>

getbit

sign

5

integer

0

統計操作,統計 打卡的天數!

127。0。0。1

6379

>

bitcount

sign

#

統計這周的打卡記錄,就可以看到是否有全勤!

integer

3

2。3 geospatial (地理位置)

Redis 的 Geo 在 Redis 3。2 版本就推出了! 這個功能可以推算地理位置的資訊: 兩地之間的距離, 方圓幾里的人

2。3。1 geoadd

新增地理位置

127。0。0。1

6379

>

geoadd

china

city

118。76

32。04

manjing

112。55

37。86

taiyuan

123。43

41。80

shenyang

integer

3

127。0。0。1

6379

>

geoadd

china

city

144。05

22。52

shengzhen

120。16

30。24

hangzhou

108。96

34。26

xian

integer

3

規則

兩級無法直接新增,我們一般會下載城市資料(這個網址可以查詢 GEO:

www。jsons。cn/lngcode

)!

有效的經度從-180度到180度。

有效的緯度從-85。05112878度到85。05112878度。

#

當座標位置超出上述指定範圍時,該命令將會返回一個錯誤。

127。0。0。1

6379

>

geoadd

china

city

39。90

116。40

beijin

error

ERR

invalid

longitude

latitude

pair

39。900000

116。400000

2。3。2 geopos

獲取指定的成員的經度和緯度

127。0。0。1

6379

>

geopos

china

city

taiyuan

manjing

1

1

“112。54999905824661255”

1

“37。86000073876942196”

2

1

“118。75999957323074341”

1

“32。03999960287850968”

獲得當前定位, 一定是一個座標值!

2。3。3 geodist

如果不存在, 返回空

單位如下

m

km

mi 英里

ft 英尺

127。0。0。1

6379

>

geodist

china

city

taiyuan

shenyang

m

“1026439。1070”

127。0。0。1

6379

>

geodist

china

city

taiyuan

shenyang

km

“1026。4391”

2。3。4 georadius

附近的人 ==> 獲得所有附近的人的地址, 定位, 透過半徑來查詢

獲得指定數量的人

127。0。0。1

6379

>

georadius

china

city

110

30

1000

km

100

30

這個座標為中心, 尋找半徑為

1000km

的城市

1

“xian”

2

“hangzhou”

3

“manjing”

4

“taiyuan”

127。0。0。1

6379

>

georadius

china

city

110

30

500

km

1

“xian”

127。0。0。1

6379

>

georadius

china

city

110

30

500

km

withdist

1

1

“xian”

2

“483。8340”

127。0。0。1

6379

>

georadius

china

city

110

30

1000

km

withcoord

withdist

count

2

1

1

“xian”

2

“483。8340”

3

1

“108。96000176668167114”

2

“34。25999964418929977”

2

1

“manjing”

2

“864。9816”

3

1

“118。75999957323074341”

2

“32。03999960287850968”

引數 key 經度 緯度 半徑 單位 [顯示結果的經度和緯度] [顯示結果的距離] [顯示的結果的數量]

2。3。5 georadiusbymember

顯示與指定成員一定半徑範圍內的其他成員

127。0。0。1

6379

>

georadiusbymember

china

city

taiyuan

1000

km

1

“manjing”

2

“taiyuan”

3

“xian”

127。0。0。1

6379

>

georadiusbymember

china

city

taiyuan

1000

km

withcoord

withdist

count

2

1

1

“taiyuan”

2

“0。0000”

3

1

“112。54999905824661255”

2

“37。86000073876942196”

2

1

“xian”

2

“514。2264”

3

1

“108。96000176668167114”

2

“34。25999964418929977”

引數與 georadius 一樣

2。3。6 geohash(較少使用)

該命令返回11個字元的hash字串

127。0。0。1

6379

>

geohash

china

city

taiyuan

shenyang

1

“ww8p3hhqmp0”

2

“wxrvb9qyxk0”

將二維的經緯度轉換為一維的字串, 如果兩個字串越接近, 則距離越近

2。3。7 底層

geo底層的實現原理實際上就是Zset, 我們可以透過Zset命令來操作geo

127。0。0。1

6379

>

type

china

city

zset

檢視全部元素 刪除指定的元素

127。0

0

1

6379

>

zrange

china:

city

0

-

1

withscores

1

“xian”

2

“4040115445396757”

3

“hangzhou”

4

“4054133997236782”

5

“manjing”

6

“4066006694128997”

7

“taiyuan”

8

“4068216047500484”

9

“shenyang”

1

“4072519231994779”

2

“shengzhen”

3

“4154606886655324”

127。0

0

1

6379

>

zrem

china:

city

manjing

integer

1

127。0

0

1

6379

>

zrange

china:

city

0

-

1

1

“xian”

2

“hangzhou”

3

“taiyuan”

4

“shenyang”

5

“shengzhen”