當前位置:
首頁 > 知識 > Redis數據類型詳解

Redis數據類型詳解

Redis數據類型

String(字元串)

string 是 redis 最基本的類型,你可以理解成與 Memcached一模一樣的類型,一個 key 對應一個 value。雖然我們現在基本都不用Memcached了。

string 類型是二進位安全的。意思是 redis 的 string 可以包含任何數據。比如jpg圖片或者序列化的對象。

string 類型是 Redis 最基本的數據類型,string 類型的值最大能存儲 512MB。

實例

redis 127.0.0.1:6379> SET name "runoob"
OK
redis 127.0.0.1:6379> GET name
"runoob"

Redis數據類型詳解

在以上實例中我們使用了 Redis 的 SETGET 命令。鍵為 name,對應的值為 runoob

String是最常用的一種數據類型,普通的key/ value 存儲都可以歸為此類,即可以完全實現目前 Memcached 的功能,並且效率更高。還可以享受Redis的定時持久化,操作日誌及 Replication等功能。除了提供與 Memcached 一樣的get、set、incr、decr 等操作外,Redis還提供了下面一些操作:

  • 獲取字元串長度
  • 往字元串append內容
  • 設置和獲取字元串的某一段內容
  • 設置及獲取字元串的某一位(bit)
  • 批量設置一系列字元串的內容

使用場景:常規key-value緩存應用。常規計數: 微博數, 粉絲數。

擴展

set mykey "wangzai" ##設置key,第二次賦值會直接覆蓋之前的
setnx mykey "wangzai" ## 如果mykey存在,則不改變,如果不存在,則創建賦值
get mykey ##獲取key的值
setex key1 10 1 ##給key1設置過期時間為10s,值為1
mset key1 value1 key2 value2 ##設置多個key
mget key1 key2 ##獲取多個key的值

Redis數據類型詳解


Hash(哈希)

Redis hash 是一個鍵值(key=>value)對集合。

Redis hash 是一個 string 類型的 field 和 value 的映射表,hash 特別適合用於存儲對象。

實例

redis> HMSET myhash field1 "Hello" field2 "World"
"OK"
redis> HGET myhash field1
"Hello"
redis> HGET myhash field2
"World"

實例中我們使用了 Redis HMSET, HGET 命令,HMSET 設置了兩個 field=>value 對, HGET 獲取對應 field 對應的 value

每個 hash 可以存儲 232 -1 鍵值對(40多億)。

Redis數據類型詳解

應用場景:

我們簡單舉個實例來描述下Hash的應用場景,比如我們要存儲一個用戶信息對象數據,包含以下信息:

用戶ID為查找的key,存儲的value用戶對象包含姓名,年齡,生日等信息,如果用普通的key/value結構來存儲,主要有以下2種存儲方式:

Redis數據類型詳解

第一種方式將用戶ID作為查找key,把其他信息封裝成一個對象以序列化的方式存儲,這種方式的缺點是,增加了序列化/反序列化的開銷,並且在需要修改其中一項信息時,需要把整個對象取回,並且修改操作需要對並發進行保護,引入CAS等複雜問題。

Redis數據類型詳解

第二種方法是這個用戶信息對象有多少成員就存成多少個key-value對兒,用用戶ID+對應屬性的名稱作為唯一標識來取得對應屬性的值,雖然省去了序列化開銷和並發問題,但是用戶ID為重複存儲,如果存在大量這樣的數據,內存浪費還是非常可觀的。

那麼Redis提供的Hash很好的解決了這個問題,Redis的Hash實際是內部存儲的Value為一個HashMap,並提供了直接存取這個Map成員的介面,如下圖:

Redis數據類型詳解

也就是說,Key仍然是用戶ID, value是一個Map,這個Map的key是成員的屬性名,value是屬性值,這樣對數據的修改和存取都可以直接通過其內部Map的Key(Redis里稱內部Map的key為field), 也就是通過 key(用戶ID) + field(屬性標籤) 就可以操作對應屬性數據了,既不需要重複存儲數據,也不會帶來序列化和並發修改控制的問題。很好的解決了問題。

這裡同時需要注意,Redis提供了介面(hgetall)可以直接取到全部的屬性數據,但是如果內部Map的成員很多,那麼涉及到遍歷整個內部Map的操作,由於Redis單線程模型的緣故,這個遍歷操作可能會比較耗時,而另其它客戶端的請求完全不響應,這點需要格外注意。

使用場景:存儲部分變更數據,如用戶信息等。

擴展

hset hash1 name wangzai ## 建立hash (hset name key value)
hget hash1 name ## 獲取field值 HGET name key
hgetall hash1 ## 獲取hash1中所有的key和value
hmset hash2 name wangzai age 26 job it ## 批量建立鍵值對
hmget hash2 name age job ## 批量獲取field值
hdel hash2 job ## 刪除指定field
hkeys hash2 ## 列印所有的key
hvals hash2 ## 列印所有的value
hlen hash2 ## 查看hash2有幾個field

List(列表)

Redis 列表是簡單的字元串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)。

實例

redis 127.0.0.1:6379> lpush runoob redis
(integer) 1
redis 127.0.0.1:6379> lpush runoob mongodb
(integer) 2
redis 127.0.0.1:6379> lpush runoob rabitmq
(integer) 3
redis 127.0.0.1:6379> lrange runoob 0 10
1) "rabitmq"
2) "mongodb"
3) "redis"
redis 127.0.0.1:6379>

列表最多可存儲 232 - 1 元素 (4294967295, 每個列表可存儲40多億)。

Redis數據類型詳解

應用場景:
Redis list的應用場景非常多,也是Redis最重要的數據結構之一,比如twitter的關注列表,粉絲列表等都可以用Redis的list結構來實現。
List 就是鏈表,相信略有數據結構知識的人都應該能理解其結構。使用List結構,我們可以輕鬆地實現最新消息排行等功能。List的另一個應用就是消息隊列,
可以利用List的PUSH操作,將任務存在List中,然後工作線程再用POP操作將任務取出進行執行。Redis還提供了操作List中某一段的api,你可以直接查詢,刪除List中某一段的元素。
實現方式:
Redis list的實現為一個雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內存開銷,Redis內部的很多實現,包括發送緩衝隊列等也都是用的這個數據結構。
Redis的list是每個子元素都是String類型的雙向鏈表,可以通過push和pop操作從列表的頭部或者尾部添加或者刪除元素,這樣List即可以作為棧,也可以作為隊列。
使用場景:
消息隊列系統
使用list可以構建隊列系統,使用sorted set甚至可以構建有優先順序的隊列系統。
比如:將Redis用作日誌收集器
實際上還是一個隊列,多個端點將日誌信息寫入Redis,然後一個worker統一將所有日誌寫到磁碟。

擴展
lpush list1 "wangzai" ##在列表中加入一個元素
lrange list1 0 -1 ##查看list1裡面的所有元素
lpop list1 ##取出list1最新的元素
linsert list1 before "wangzai" "doubi" ##在值為"wangzai"的前面插入一個元素為"doubi"
lset list1 3 "hehe" ##把第五個元素修改為"hehe"
lindex list1 0 ##查看第一個元素
llen list1 ##查看列表中有多少元素


Set(集合)

Redis的Set是string類型的無序集合。

集合是通過哈希表實現的,所以添加,刪除,查找的複雜度都是O(1)。

sadd 命令

添加一個 string 元素到 key 對應的 set 集合中,成功返回1,如果元素已經在集合中返回 0,如果 key 對應的 set 不存在則返回錯誤。

sadd key member

實例

redis 127.0.0.1:6379> sadd runoob redis
(integer) 1
redis 127.0.0.1:6379> sadd runoob mongodb
(integer) 1
redis 127.0.0.1:6379> sadd runoob rabitmq
(integer) 1
redis 127.0.0.1:6379> sadd runoob rabitmq
(integer) 0
redis 127.0.0.1:6379> smembers runoob
1) "redis"
2) "rabitmq"
3) "mongodb"

注意:以上實例中 rabitmq 添加了兩次,但根據集合內元素的唯一性,第二次插入的元素將被忽略。

集合中最大的成員數為 232 - 1(4294967295, 每個集合可存儲40多億個成員)。

應用場景:

Redis set對外提供的功能與list類似是一個列表的功能,特殊之處在於set是可以自動排重的,當你需要存儲一個列表數據,又不希望出現重複數據時,set是一個很好的選擇,並且set提供了判斷某個成員是否在一個set集合內的重要介面,這個也是list所不能提供的。

Set 就是一個集合,集合的概念就是一堆不重複值的組合。利用Redis提供的Set數據結構,可以存儲一些集合性的數據。

案例:

在微博應用中,可以將一個用戶所有的關注人存在一個集合中,將其所有粉絲存在一個集合。Redis還為集合提供了求交集、並集、差集等操作,可以非常方便的實現如共同關注、共同喜好、二度好友等功能,對上面的所有集合操作,你還可以使用不同的命令選擇將結果返回給客戶端還是存集到一個新的集合中。

Set是集合,是String類型的無序集合,set是通過hashtable實現的,概念和數學中個的集合基本類似,可以交集,並集,差集等等,set中的元素是沒有順序的。

擴展

sadd set1 a b c d ## 創建集合set1並設置值
smembers set1 ## 查看集合set1的值
srem set1 a b ## 刪除set1的值
spop set1 ## 隨機取出一個元素並刪除
sinter set1 set2 ## 交集
sinterstore set1 set2 set3 ## 將交集存儲到set3
sunion set1 set2 ## 並集
sunionstore set1 set2 set3 ## 把並集存儲到set3
sdiff set1 set2 ## 差集
sdiffstore set1 set2 set3 ## 把差集存儲到set3
sismember set1 c ## 判斷一個元素是否屬於一個集合
srandmember set1 ## 隨機取出一個元素,但不刪除


zset(sorted set:有序集合)

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

zset的成員是唯一的,但分數(score)卻可以重複。

zadd 命令

添加元素到集合,元素在集合中存在則更新對應score

zadd key score member

實例

redis 127.0.0.1:6379> zadd runoob 0 redis
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 mongodb
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 rabitmq
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 rabitmq
(integer) 0
redis 127.0.0.1:6379> > ZRANGEBYSCORE runoob 0 1000
1) "mongodb"
2) "rabitmq"
3) "redis"

使用場景:

Redis sorted set的使用場景與set類似,區別是set不是自動有序的,而sorted set可以通過用戶額外提供一個優先順序(score)的參數來為成員排序,並且是插入有序的,即自動排序。當你需要一個有序的並且不重複的集合列表,那麼可以選擇sorted set數據結構,比如twitter 的public timeline可以以發表時間作為score來存儲,這樣獲取時就是自動按時間排好序的。

和Set相比,Sorted Set增加了一個權重參數score,使得集合中的元素能夠按score進行有序排列,比如一個存儲全班同學成績的Sorted Set,其集合value可以是同學的學號,而score就可以是其考試得分,這樣在數據插入集合的時候,就已經進行了天然的排序。另外還可以用Sorted Set來做帶權重的隊列,比如普通消息的score為1,重要消息的score為2,然後工作線程可以選擇按score的倒序來獲取工作任務。讓重要的任務優先執行。

實現方式:

Redis sorted set的內部使用HashMap和跳躍表(SkipList)來保證數據的存儲和有序,HashMap里放的是成員到score的映射,而跳躍表裡存放的是所有的成員,排序依據是HashMap里存的score,使用跳躍表的結構可以獲得比較高的查找效率,並且在實現上比較簡單。



喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 青峰科技 的精彩文章:

為什麼Redis這麼快?
vsphere虛擬化方案配置及使用

TAG:青峰科技 |