Redis的數(shù)據(jù)結(jié)構(gòu)
redis是一種高級(jí)的key-value的存儲(chǔ)系統(tǒng)以清,其中value支持五種數(shù)據(jù)類型弥激。
- 字符串(String)
- 哈希(hash)
- 字符串列表(list)
- 字符串集合(set)
- 有序字符串集合(sorted set)
1. 存儲(chǔ)字符串String
字符串類型是Redis中最為基礎(chǔ)的數(shù)據(jù)存儲(chǔ)類型,它在Redis中是二進(jìn)制安全的,這便意味著該類型可以接受任何格式的數(shù)據(jù),如JPEG圖像數(shù)據(jù)或json對(duì)象描述信息等。在Redis中字符串類型的value最多可以容納的數(shù)據(jù)長(zhǎng)度是512M您宪。
以下是常用命令:
- 賦值
設(shè)定key持有指定的字符串value,如果該key存在則進(jìn)行覆蓋操作奠涌∠芫蓿總是返回OK。
[root@itzhouq32 bin]# ./redis-cli
127.0.0.1:6379> set username tom
OK
- 取值
獲取key的value溜畅。如果與該key關(guān)聯(lián)的value不是String類型捏卓,redis將返回錯(cuò)誤信息,因?yàn)間et命令只能用于獲取String value;如果key不存在怠晴,返回nil遥金。
127.0.0.1:6379> get username
"tom"
127.0.0.1:6379> get xxx
(nil)
- 先取值再賦值
getset key value :先獲取該key的值,然后再設(shè)置該key的值蒜田。
127.0.0.1:6379> getset username jack
"tom"
127.0.0.1:6379> get username
"jack"
127.0.0.1:6379>
- 刪除
del key :刪除指定key
127.0.0.1:6379> set age 20
OK
127.0.0.1:6379> del age
(integer) 1
127.0.0.1:6379> get age
(nil)
127.0.0.1:6379>
- 數(shù)值增減
incr key : 將指定的key的value原子性的增加1稿械。如果該key不存在,其初始值為0冲粤。在incr之后其值為1.如果value的值不能轉(zhuǎn)成整型美莫,該操作將執(zhí)行失敗并返回相應(yīng)的錯(cuò)誤信息。
127.0.0.1:6379> incr num
(integer) 1
127.0.0.1:6379> get num
"1"
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> get num
"2"
127.0.0.1:6379> incr hello
(integer) 1
127.0.0.1:6379> get hello
"1"
127.0.0.1:6379> set world china
OK
127.0.0.1:6379> incr world
(error) ERR value is not an integer or out of range
decr key : 將指定的key的value原子性的遞減1.如果該key不存在梯捕,其初始值為0厢呵,在incr之后其值為-1.如果value的值不能轉(zhuǎn)成整型,該操作將執(zhí)行失敗并返回相應(yīng)的錯(cuò)誤信息傀顾。
127.0.0.1:6379> decr num2
(integer) -1
127.0.0.1:6379> get num2
"-1"
incrby increment : 將指定的key的value原子性的增加increment襟铭。如果key不存在,其初始值為0.如果該值不能轉(zhuǎn)化為整型短曾,報(bào)錯(cuò)寒砖。
127.0.0.1:6379> incrby date 10
(integer) 10
127.0.0.1:6379> get date
"10"
decrby decrement :將指定的值原子性減少。
127.0.0.1:6379> decrby day 5
(integer) -5
127.0.0.1:6379> get day
"-5"
- 拼接字符串
append key value : 拼接字符串嫉拐。如果key存在哩都,則在原有的基礎(chǔ)上追加該值;如果該key不存在椭岩,則重新創(chuàng)建一個(gè)key/value茅逮。返回值為字符串的長(zhǎng)度璃赡。
127.0.0.1:6379> append username 123
(integer) 7
127.0.0.1:6379> get username
"jack123"
127.0.0.1:6379> append yyy 123
(integer) 3
127.0.0.1:6379> get yyy
"123"
2. 存儲(chǔ)Hash
Redis中的Hash類型可以看成具有String key 和String value的map容器判哥。所以該類型非常適合于存儲(chǔ)對(duì)象的信息。如Username碉考、password和age塌计。如果Hash中包含少量的字段,那么該類型的數(shù)據(jù)也將僅占用很少的磁盤(pán)空間侯谁。
常用命令:
- 賦值
hset key field value : 為指定的key設(shè)定field/value對(duì)(鍵值對(duì))锌仅。
hmset key field value [field2 value2 ......] : 設(shè)置key中多個(gè)field/value。
127.0.0.1:6379> hset myhash username jack
(integer) 1
127.0.0.1:6379> hset myhash age 18
(integer) 1
127.0.0.1:6379> hmset myhash2 username rose age 21
OK
- 取值
hget key field : 返回指定key中的field的值
hmget key field : 獲取key中的多個(gè)field的值
hgetall key : 獲取key中所有的field-value
127.0.0.1:6379> hget myhash username
"jack"
127.0.0.1:6379> hmget myhash username age
1) "jack"
2) "18"
127.0.0.1:6379> hgetall myhash
1) "username"
2) "jack"
3) "age"
4) "18"
- 刪除
hdel key field [field ...] : 可以刪除一個(gè)或者多個(gè)字段墙贱,返回值是被刪除的字段的個(gè)數(shù)热芹。
del key : 刪除整個(gè)hash
127.0.0.1:6379> hgetall myhash2
1) "username"
2) "rose"
3) "age"
4) "21"
127.0.0.1:6379> hdel myhash2 username age
(integer) 2
127.0.0.1:6379> hgetall myhash2
(empty list or set)
127.0.0.1:6379> hmset myhash3 username marry age 20 addr shanghai
OK
127.0.0.1:6379> hgetall myhash3
1) "username"
2) "marry"
3) "age"
4) "20"
5) "addr"
6) "shanghai"
127.0.0.1:6379> del myhash3
(integer) 1
127.0.0.1:6379> hgetall myhash3
(empty list or set)
- 增加數(shù)字
hincrby key field increment : 設(shè)置key中field的值增加increment。
127.0.0.1:6379> hget myhash age
"18"
127.0.0.1:6379> hincrby myhash age 5
(integer) 23
127.0.0.1:6379> hget myhash age
"23"
127.0.0.1:6379> hincrby myhash age -10
(integer) 13
127.0.0.1:6379> hget myhash age
"13"
- 判斷
hexists key field : 判斷指定的key中的field是否存在
127.0.0.1:6379> hexists myhash password
(integer) 0
127.0.0.1:6379> hexists myhash username
(integer) 1
- 獲取key所包含的field的數(shù)量
127.0.0.1:6379> hgetall myhash
1) "username"
2) "jack"
3) "age"
4) "13"
127.0.0.1:6379> hlen myhash
(integer) 2
- 獲取所有的ekey
hkey key
127.0.0.1:6379> hkeys myhash
1) "username"
2) "age"
- 獲取所有的value
127.0.0.1:6379> hvals myhash
1) "jack"
2) "13"
3. 存儲(chǔ)List類型
在Redis中惨撇,List類型是按照插入順序排序的字符串鏈表伊脓。和數(shù)據(jù)結(jié)構(gòu)中的普通鏈表 一樣,我們可以在其頭部(left)和尾部(right)添加新的元素魁衙。在插入時(shí)报腔,如果該鍵并不存在株搔,Redis將為該鍵創(chuàng)建一個(gè)新的鏈表。與此相反纯蛾,如果鏈表中所有的元素均被移除纤房,那么該鍵也將會(huì)被從數(shù)據(jù)庫(kù)中刪除。
從元素插入和刪除的效率視角來(lái)看翻诉,如果我們是在鏈表的兩頭插入或刪除元素炮姨,這將會(huì)是非常高效的操作,即使鏈表中已經(jīng)存儲(chǔ)了百萬(wàn)條記錄米丘,該操作也可以在常量時(shí)間內(nèi)完成剑令。然而需要說(shuō)明的是,如果元素插入或刪除操作是作用于鏈表中間拄查,那將會(huì)是非常低效的吁津。相信對(duì)于有良好數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)的開(kāi)發(fā)者而言,這一點(diǎn)并不難理解堕扶。
ArrayList使用數(shù)組的方式存儲(chǔ)數(shù)據(jù)碍脏,所以根據(jù)索引查詢數(shù)據(jù)速度快,而新增或者刪除元素時(shí)稍算,涉及到位移操作典尾,所以比較慢。
LinkedList使用雙向鏈表糊探,每一個(gè)元素都記錄前后元素的指針钾埂,所以插入、刪除數(shù)據(jù)時(shí)只是更改前后元素的指針指向即可科平,速度非橙熳希快。然后通過(guò)記錄下標(biāo)查詢?cè)貢r(shí)需要從頭開(kāi)始索引瞪慧,所以比較慢髓考。
以下為常用命令:
- 查看列表
lrange key start end : 獲取鏈表中從start到end的元素的值,start弃酌、end從0開(kāi)始計(jì)數(shù)氨菇;也可以為負(fù)數(shù),若為-1則表示鏈表尾部的元素妓湘。
127.0.0.1:6379> lrange mylist 0 -1
1) "c"
2) "b"
3) "a"
-
兩端添加
lpush key value [value1 value2]... : 在指定的key所關(guān)聯(lián)的list的頭部插入所有的values查蓉,如果該key不存在,該命令在插入前創(chuàng)建一個(gè)與該key關(guān)聯(lián)的空鏈表榜贴,之后再向鏈表的頭部插入數(shù)據(jù)豌研。插入成功,返回元素的個(gè)數(shù)。rpush key value [value1 value2]... : 在該list的尾部添加元素聂沙。
127.0.0.1:6379> lpush mylist2 a b c d
(integer) 4
127.0.0.1:6379> rpush mylist2 1 2 3
(integer) 7
127.0.0.1:6379> lrange mylist2 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
5) "1"
6) "2"
7) "3"
- 兩端彈出
lpop key : 返回并彈出指定key關(guān)聯(lián)得鏈表中得第一個(gè)元素秆麸,即頭部元素。如果該key不存在及汉,返回nil沮趣。
rpop key : 從尾部彈出元素。
127.0.0.1:6379> lpop mylist2
"d"
127.0.0.1:6379> lrange mylist2 0 -1
1) "c"
2) "b"
3) "a"
4) "1"
5) "2"
6) "3"
127.0.0.1:6379> rpop mylist2
"3"
127.0.0.1:6379> lrange mylist2 0 -1
1) "c"
2) "b"
3) "a"
4) "1"
5) "2"
4. 存儲(chǔ)set類型
在redis中坷随,可以將Set類型看作是沒(méi)有排序的字符集合房铭,和List類型一樣,我們也可以在該類型的數(shù)值上執(zhí)行添加温眉、刪除和判斷某一元素是否存在等操作缸匪。這些操作的時(shí)間復(fù)雜度為O(1),即常量時(shí)間內(nèi)完成依次操作。
和List類型不同的是类溢,Set集合中不允許出現(xiàn)重復(fù)的元素凌蔬。
常用命令:
- 增加/刪除元素
sadd key values[ value1 value2...] : 向set中添加數(shù)據(jù),如果key的值已經(jīng)存在則不會(huì)重復(fù)添加闯冷。
srem key members[member1 member2...] : 刪除set中指定的成員
127.0.0.1:6379> sadd myset a b c
(integer) 3
127.0.0.1:6379> srem myset 1 2
(integer) 0
127.0.0.1:6379> srem myset a b
(integer) 2
- 獲得集合的元素
smembers key : 獲取set中所有的成員
sismember key member:判斷參數(shù)指定的成員是否在該set中砂心,1表示存在,0表示不存在蛇耀,或者該key本身不存在辩诞。
127.0.0.1:6379> smembers myset
1) "c"
127.0.0.1:6379> sismember myset a
(integer) 0
127.0.0.1:6379> sismember myset c
(integer) 1
- 集合的差集運(yùn)算
sdiff key1 key2...:返回key1與key2中相差的成員,而且與key的順序有關(guān)纺涤,即返回差集译暂。
127.0.0.1:6379> sadd mya1 a b c
(integer) 3
127.0.0.1:6379> sadd myb1 a c 1 2
(integer) 4
127.0.0.1:6379> sdiff mya1 myb1
1) "b"
- 集合的交集運(yùn)算
sinter key1 key2 key3 : 返回交集
127.0.0.1:6379> smembers mya1
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> smembers myb1
1) "a"
2) "1"
3) "2"
4) "c"
127.0.0.1:6379> sinter mya1 myb1
1) "a"
2) "c"
- 集合的并集運(yùn)算
sunion key1 key2 key3 ....:返回并集
127.0.0.1:6379> sunion mya1 myb1
1) "1"
2) "b"
3) "c"
4) "a"
5) "2"
- set的使用場(chǎng)景
可以使用Redis的set數(shù)據(jù)類型跟蹤一些唯一性數(shù)據(jù),比如訪問(wèn)某一個(gè)博客的唯一IP地址信息撩炊。對(duì)于此場(chǎng)景外永,我們僅需在每次訪問(wèn)該博客時(shí)將訪問(wèn)者的IP存入redis中,set集合類型會(huì)自動(dòng)保證IP地址的唯一性衰抑。
充分利用Set類型的服務(wù)端聚合操作方便象迎、高效的特性荧嵌,可以用于維護(hù)數(shù)據(jù)對(duì)象之間的關(guān)聯(lián)關(guān)系呛踊。比如所有購(gòu)買某一電子設(shè)備的客戶ID被存儲(chǔ)在一個(gè)特定的set中,而購(gòu)買另一種電子產(chǎn)品的客戶ID被存儲(chǔ)在另外一個(gè)set中啦撮,如果此時(shí)我們想獲取有哪些客戶同時(shí)購(gòu)買了這兩種商品時(shí)谭网,set的一些命令可以充分發(fā)揮優(yōu)勢(shì)了。
5. 存儲(chǔ)sortedset類型
sortedset和set極為相似赃春,他們都是字符串的集合愉择,都不允許重復(fù)的成員出現(xiàn)在一個(gè)set中。他們之間的主要差別是sortedset中每一個(gè)成員都會(huì)有一個(gè)分?jǐn)?shù)與之關(guān)聯(lián)。redis正是通過(guò)分?jǐn)?shù)來(lái)為集合的成員進(jìn)行從小到大的排序锥涕。sortedset中分?jǐn)?shù)是可以重復(fù)的衷戈。
常見(jiàn)命令:
- 添加元素
zadd key score member score2 member2...:將成員以及該成員的分?jǐn)?shù)存放到sortedset中。如果該元素已經(jīng)存在則會(huì)用新的分?jǐn)?shù)替換原有的分?jǐn)?shù)层坠。返回值是新加入到集合的元素的個(gè)數(shù)殖妇,不包含之前已經(jīng)存在的元素。
127.0.0.1:6379> zadd mysort 70 zhangsan 80 lisi 60 wangwu
(integer) 3
127.0.0.1:6379> zadd mysort 100 zhangsan
(integer) 0
- 獲取元素
zscore key member :返回指定成員的分?jǐn)?shù)
127.0.0.1:6379> zscore mysort zhangsan
"100"
zcard key : 獲取集合中成員數(shù)量
127.0.0.1:6379> zcard mysort
(integer) 3
- 刪除元素
zrem key member [member...] : 移除集合中指定的成員破花,可以指定多個(gè)成員
127.0.0.1:6379> zrem mysort wangwu lisi
(integer) 2
- 范圍查詢
zrange key start end [withscores] : 獲取集合中腳注為start-end的成員谦趣,[withscores]參數(shù)表明返回的成員包含其分?jǐn)?shù)。
27.0.0.1:6379> zadd mysort 20 qianqi 89 zhaoba
(integer) 2
127.0.0.1:6379> zadd mysort 50 jack 98 rose
(integer) 2
127.0.0.1:6379> zrange mysort 0 -1
1) "qianqi"
2) "jack"
3) "zhaoba"
4) "rose"
5) "zhangsan"
127.0.0.1:6379> zrange mysort 0 -1 withscores
1) "qianqi"
2) "20"
3) "jack"
4) "50"
5) "zhaoba"
6) "89"
7) "rose"
8) "98"
9) "zhangsan"
10) "100"
zrevrange key start stop [withscores] : 按照分?jǐn)?shù)從大到小的順序返回索引從start到stop之間的所有元素(包含兩端的元素)座每。
127.0.0.1:6379> zrevrange mysort 0 -1 withscores
1) "zhangsan"
2) "100"
3) "rose"
4) "98"
5) "zhaoba"
6) "89"
7) "jack"
8) "50"
9) "qianqi"
10) "20"
zremrangebyrank key start stop : 按照排名范圍刪除元素
127.0.0.1:6379> zremrangebyrank mysort 0 4
(integer) 5
- 使用場(chǎng)景
可以用于一個(gè)大型在線游戲的積分排行榜前鹅。每當(dāng)玩家的分?jǐn)?shù)發(fā)生變化時(shí),可以執(zhí)行zadd命令更改新玩家的分?jǐn)?shù)峭梳,此后再通過(guò)zrange命令獲取積分top10的用戶信息舰绘。
sortedset類型還可以用于構(gòu)建索引數(shù)據(jù)。