天天看點

【資料庫】Redis(2)--Redis的常用資料類型及指令

【資料庫】Redis(2)--Redis的常用資料類型及指令

1.Redis主要資料類型分類

Redis中存儲資料常用的資料類型主要有五種:String、List、Set、Sorted Set、Hash,這五種資料結構在Redis中存儲資料的指令掌握對于我們後期在使用Java架構封裝類操作Redis的API了解是非常重要的。是以在這裡對這五種資料結構進行一一彙總,另外也簡單介紹一下bitmaps、hyperloglogs、geospatial這三種類型。

【資料庫】Redis(2)--Redis的常用資料類型及指令

1.1.String類型

String類型在Redis中常用的操作:

①get/set/exists/append/strlen指令:

127.0.0.1:6379> set key1 v1  # 設定值
OK 
127.0.0.1:6379> get key1    # 擷取值"v1"127.0.0.1:6379> keys *    # 擷取所有的值1) "key1"127.0.0.1:6379> EXISTS key1    # 判斷key1是否存在
(integer) 1127.0.0.1:6379> APPEND key1 "hello"    # 向key1中追加"hello",如果Key1不存在,那就相當于set key1(integer) 7127.0.0.1:6379> get key1"v1hello"127.0.0.1:6379> STRLEN key1    #擷取字元串的長度
(integer) 7127.0.0.1:6379> APPEND key1 ", fengye"(integer) 15127.0.0.1:6379> STRLEN key1
(integer) 15127.0.0.1:6379> get key1"v1hello, fengye"      

②自增/減、步長(浏覽量、點選數):

# +1/-1與+n/-n
127.0.0.1:6379> set views 0OK127.0.0.1:6379> get views"0"127.0.0.1:6379> incr views  # 自增+1
(integer) 1127.0.0.1:6379> incr views
(integer) 2127.0.0.1:6379> get views"2"127.0.0.1:6379> decr views  # 自減-1
(integer) 1127.0.0.1:6379> decr views
(integer) 0127.0.0.1:6379> decr views
(integer) -1127.0.0.1:6379> get views"-1"127.0.0.1:6379> INCRBY views 10  # 增加 n(integer) 9127.0.0.1:6379> INCRBY views 10(integer) 19127.0.0.1:6379> DECRBY views 5   # 減少 n(integer) 14      

③字元串截取:

127.0.0.1:6379> set key1 "hello, fengye"OK127.0.0.1:6379> get key1"hello, fengye"127.0.0.1:6379> GETRANGE key1 0 4    # 截取閉區間 [0, 4]的字元串"hello"127.0.0.1:6379> GETRANGE key1 0 -1   # 截取全部的字元串,和get key1同理"hello, fengye"      

④替換:

127.0.0.1:6379> set key2 abcddefg
OK127.0.0.1:6379> get key2"abcddefg"127.0.0.1:6379> SETRANGE key2 2 XXX   #  替換指定位置開始的字元串
(integer) 8127.0.0.1:6379> get key2"abXXXefg"      

⑤setex(set with expire)與setnx(set if not exist):

#setex :設定過期時間
#setnx :不存在目前key才會設定值,在分布式鎖中常常使用
127.0.0.1:6379> setex key3 30 "hello"   # 設定過期時間為30s,30s後過期OK127.0.0.1:6379> ttl key3
(integer) 21127.0.0.1:6379> get key3"hello"127.0.0.1:6379> setnx mykey "redis"   #設定mykey的值為redis,當mykey不存在時設定成功(integer) 1127.0.0.1:6379> keys *1) "key1"2) "key2"3) "mykey"127.0.0.1:6379> ttl key3
(integer) -2127.0.0.1:6379> setnx mykey "mongoDb"   #當mykey已經存在了,設定mykey會失敗(integer) 0127.0.0.1:6379> get mykey"redis"      

⑥同時設定多個值mset/mget/msetnx:

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3    #同時設定多個值
OK127.0.0.1:6379> keys *1) "k3"2) "k2"3) "k1"127.0.0.1:6379> mget k1 k2 k3    #同時擷取多個值1) "v1"2) "v2"3) "v3"127.0.0.1:6379> msetnx k1 y1 k4 v4   #同時擷取多個值,msetnx是一個原子性操作,要麼一起成功,要麼一起失敗
(integer) 0 

127.0.0.1:6379> get k4 
(nil)      

⑦設定對象的值:

127.0.0.1:6379> set user:2 {name:lisi,age:3}   # 使用json字元串來儲存user的值
OK127.0.0.1:6379> get user:2"{name:lisi,age:3}"127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2   # 使用user:1:name與user1:1:age來儲存值,user:{id}:{field}作為key來儲存值OK127.0.0.1:6379> mget user:1:name user:1:age1) "zhangsan"2) "2"      

⑧getset(先擷取後設定):

127.0.0.1:6379> getset db redis  #如果不存在值,則傳回nil,并設定初始值
(nil)127.0.0.1:6379> get db"redis"127.0.0.1:6379> getset db mongodb  #如果存在值,則傳回那個值,并設定新的值"redis"127.0.0.1:6379> get db"mongodb"      

1.2.List類型

①lpush/rpush/lrange(壓棧):

127.0.0.1:6379> LPUSH list one   # 将一個或多個值放到清單的頭部(左push)
(integer) 1127.0.0.1:6379> LPUSH list two
(integer) 2127.0.0.1:6379> LPUSH list three
(integer) 3127.0.0.1:6379> LRANGE list 0 -11) "three"2) "two"3) "one"127.0.0.1:6379> LRANGE list 0 11) "three"2) "two"127.0.0.1:6379> RPUSH list four    # 将一個或多個值放到清單的尾部(右push)
(integer) 4127.0.0.1:6379> LRANGE list 0 -11) "three"2) "two"3) "one"4) "four"      

②lpop/rpop:

127.0.0.1:6379> LPOP list  # 左移除清單中的一個元素"three"127.0.0.1:6379> RPOP list  # 右移除清單中的一個元素"four"127.0.0.1:6379> LRANGE list 0 -11) "two"2) "one"      

③lindex(list index的簡寫):

127.0.0.1:6379> LINDEX list 1  # 通過下标獲得list中的某一個值"one"127.0.0.1:6379> LINDEX list 0"two"      

④llen:

127.0.0.1:6379> LPUSH list one
(integer) 1127.0.0.1:6379> LPUSH list two
(integer) 2127.0.0.1:6379> LPUSH list three
(integer) 3127.0.0.1:6379> Llen list  # 傳回清單的長度
(integer) 3      

⑤Lrem:

127.0.0.1:6379> LRANGE list 0 -11) "three"2) "three"3) "two"4) "one"127.0.0.1:6379> lrem list 1 one   # 移除list集合中指定個數的元素,精确比對個數并移除
(integer) 1127.0.0.1:6379> LRANGE list 0 -11) "three"2) "three"3) "two"127.0.0.1:6379> lrem list 1 three
(integer) 1127.0.0.1:6379> LRANGE list 0 -11) "three"2) "two"127.0.0.1:6379> LPUSH list three
(integer) 3127.0.0.1:6379> lrem list 2 three
(integer) 2127.0.0.1:6379> LRANGE list 0 -11) "two"      

⑥Lrem:

127.0.0.1:6379> Rpush mylist "hello"(integer) 1127.0.0.1:6379> Rpush mylist "hello1"(integer) 2127.0.0.1:6379> Rpush mylist "hello2"(integer) 3127.0.0.1:6379> Rpush mylist "hello3"(integer) 4127.0.0.1:6379> Ltrim mylist 1 2   # 通過下标截取指定的長度,截取之後List會被改變,隻剩下截取後的元素OK127.0.0.1:6379> LRANGE list 0 -1(empty list or set)127.0.0.1:6379> LRANGE mylist 0 -11) "hello1"2) "hello2"      

⑦rpoplpush:

127.0.0.1:6379> rpush mylist "hello"(integer) 1127.0.0.1:6379> rpush mylist "hello1"(integer) 2127.0.0.1:6379> rpush mylist "hello2"(integer) 3127.0.0.1:6379> rpoplpush mylist myotherlist  #右彈棧,移除清單中最後一個元素并放入新的清單元素中"hello2"127.0.0.1:6379> lrange mylist 0 -11) "hello"2) "hello1"127.0.0.1:6379> lrange myotherlist 0 -11) "hello2"      

⑧lset:

lset:将清單中指定下标的一個元素替換成另外一個元素,更新操作

127.0.0.1:6379> EXISTS list
(integer) 0127.0.0.1:6379> lset list 0 item   #判斷清單是否存在,如果不存在的話,目前更新會報錯
(error) ERR no such key127.0.0.1:6379> lpush list value1
(integer) 1127.0.0.1:6379> LRANGE list 0 01) "value1"127.0.0.1:6379> lset list 0 item   #如果清單已經存在元素,可以更新目前清單中的元素
OK127.0.0.1:6379> LRANGE list 0 01) "item"127.0.0.1:6379> lset list 1 other   #如果更新範圍超出限制,也會抛出異常
(error) ERR index out of range      

⑨Linsert:

Linsert将某一個具體的value插入到清單中的某個元素的前面或者後面

127.0.0.1:6379> Rpush mylist "hello"(integer) 1127.0.0.1:6379> Rpush mylist "world"(integer) 2127.0.0.1:6379> LINSERT mylist before "world" "other"(integer) 3127.0.0.1:6379> LRANGE mylist 0 -11) "hello"2) "other"3) "world"127.0.0.1:6379> LINSERT mylist after "world" "new"(integer) 4127.0.0.1:6379> LRANGE mylist 0 -11) "hello"2) "other"3) "world"4) "new"      

1.3.Set類型

redis中Set集合中的元素是不能重複的。

①sadd/smembers/sismember/scard

127.0.0.1:6379> sadd myset "hello"(integer) 1127.0.0.1:6379> sadd myset "fengye"(integer) 1127.0.0.1:6379> sadd myset "love fengye"(integer) 1127.0.0.1:6379> SMEMBERS myset  #檢視myset中所有的值1) "fengye"2) "love fengye"3) "hello"127.0.0.1:6379> SISMEMBER myset hello  #判斷某一個值是不是在set集合中
(integer) 1127.0.0.1:6379> SISMEMBER myset world
(integer) 0      

  127.0.0.1:6379> scard myset  #擷取set集合中内容元素的個數

  (integer) 4

②srem

127.0.0.1:6379> SMEMBERS myset1) "fengye"2) "lovekuangshen2"3) "love fengye"4) "hello"127.0.0.1:6379> srem myset lovekuangshen2   #移除某一個元素
(integer) 1127.0.0.1:6379> SMEMBERS myset1) "fengye"2) "love fengye"3) "hello"      

③srandmember

127.0.0.1:6379> SRANDMEMBER myset"hello"127.0.0.1:6379> SRANDMEMBER myset"love fengye"127.0.0.1:6379> SRANDMEMBER myset"fengye"127.0.0.1:6379> SRANDMEMBER myset 2  #随機抽選出指定個數的元素1) "hello"2) "love fengye"      

④spop

127.0.0.1:6379> spop myset  #随機删除集合中的一些元素"fengye"127.0.0.1:6379> spop myset"love fengye"127.0.0.1:6379> SMEMBERS myset1) "hello"      

⑤smove

127.0.0.1:6379> sadd myset "hello"(integer) 1127.0.0.1:6379> sadd myset "world"(integer) 1127.0.0.1:6379> sadd myset "fengye"(integer) 1127.0.0.1:6379> sadd myset2 "set2"(integer) 1127.0.0.1:6379> smove myset myset2 "fengye"  #将指定的元素從一個set移動到另一個set集合中(integer) 1127.0.0.1:6379> SMEMBERS myset1) "world"2) "hello"127.0.0.1:6379> SMEMBERS myset21) "fengye"2) "set2"      

⑥sdiff/sinter/sunion

127.0.0.1:6379> sadd key1 a
(integer) 1127.0.0.1:6379> sadd key1 b
(integer) 1127.0.0.1:6379> sadd key1 c
(integer) 1127.0.0.1:6379> sadd key2 c
(integer) 1127.0.0.1:6379> sadd key2 d
(integer) 1127.0.0.1:6379> sadd key2 e
(integer) 1127.0.0.1:6379> SDIFF key1 key2   # 差集1) "a"2) "b"127.0.0.1:6379> SINTER key1 key2  # 交集1) "c"127.0.0.1:6379> SUNION key1 key2  # 并集1) "a"2) "b"3) "c"4) "d"5) "e"      

1.4.Hash

①hset/hget/hmget/hgetall:

127.0.0.1:6379> hset myhash field1 fengye  # hset一個具體的key-value
(integer) 1127.0.0.1:6379> hget myhash field1"fengye"127.0.0.1:6379> hmset myhash field1 hello field2 world    #set多個key value
OK127.0.0.1:6379> hmget myhash field1 field2    #擷取多個字段值1) "hello"2) "world"127.0.0.1:6379> hgetall myhash  #擷取全部的資料1) "field1"2) "hello"3) "field2"4) "world"

#使用hash存取對象資料      

127.0.0.1:6379> hmset myhash username zhangsan sex '男' age 24

OK

127.0.0.1:6379> HGETALL myhash

1) "field2"

2) "world"

3) "field1"

4) "hello"

5) "field3"

6) "5"

7) "filed3"

8) "1"

9) "field4"

10) "hello"

11) "username"

12) "zhangsan"

13) "sex"

14) "\xe7\x94\xb7"

15) "age"

16) "24"

②hdel:

127.0.0.1:6379> hdel myhash field1  #删除hash中指定的key字段,對應的value值也就沒有了
(integer) 1127.0.0.1:6379> hgetall myhash1) "field2"2) "world"      

③hlen:

127.0.0.1:6379> HGETALL myhash1) "field2"2) "world"3) "field1"4) "hello"127.0.0.1:6379> hlen myhash  # 擷取hash表的字段數量
(integer) 2      

④hexists:

127.0.0.1:6379> HEXISTS myhash field1  #判斷hash中的key是否存在
(integer) 1127.0.0.1:6379> HEXISTS myhash field3
(integer) 0      

⑤Hkeys/Hvals:

127.0.0.1:6379> HKEYS myhash   # 查詢所有的keys1) "field2"2) "field1"127.0.0.1:6379> HVALS myhash   # 查詢所有的vals1) "world"2) "hello"      

⑥hincrby/hsetnx:

127.0.0.1:6379> hset myhash field3 5(integer) 1127.0.0.1:6379> HINCRBY myhash field3 1  #hash指定增量
(integer) 6127.0.0.1:6379> HINCRBY myhash field3 -1  #hash自減
(integer) 5127.0.0.1:6379> hsetnx myhash field4 hello   #不存在則設定值
(integer) 1127.0.0.1:6379> hsetnx myhash field4 world  #存在則無法設定,分布式鎖
(integer) 0      

1.5.Sorted Set有序集合類

①zadd/zrange:

127.0.0.1:6379> zadd myset 1 one  #添加一個值
(integer) 1127.0.0.1:6379> zadd myset 2 two 3 three   #添加多個值
(integer) 2127.0.0.1:6379> ZRANGE myset 0 -11) "one"2) "two"3) "three"      

②zrangebyscore:

127.0.0.1:6379> clear127.0.0.1:6379> zadd salary 2500 xiaohong
(integer) 1127.0.0.1:6379> zadd salary 4000 zhangsan
(integer) 1127.0.0.1:6379> zadd salary 1000 fengye
(integer) 1127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf  #按照薪資高低升序排序1) "fengye"2) "xiaohong"3) "zhangsan"127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores  #按照薪資高低升序排序,附帶薪資

1) "fengye" 
2) "1000" 
3) "xiaohong" 
4) "2500" 
5) "zhangsan" 
6) "4000"      
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 2500 withscores 

1) "fengye" 
2) "1000" 
3) "xiaohong" 
4) "2500"      

③zrem:

127.0.0.1:6379> ZREM salary zhangsan  #移除sorted set中指定的元素
(integer) 1127.0.0.1:6379> ZRANGE salary 0 -11) "fengye"      

④zcard:

127.0.0.1:6379> ZCARD salary  #擷取有序集合中元素的個數
(integer) 2      

⑤zrevrage:

127.0.0.1:6379> ZREVRANGE salary 0 -1 withscores  #從大到小排列1) "xiaohong" 2) "2500"3) "fengye"4) "1000"      

⑥zcount:

127.0.0.1:6379> zadd myset 1 hello
(integer) 1127.0.0.1:6379> zadd myset 2 world 3 fengye
(integer) 2127.0.0.1:6379> zcount myset 1 3  #擷取指定區間的成員數量
(integer) 3127.0.0.1:6379> zcount myset 1 2(integer) 2      

2.Redis幾種特殊類型分類

2.1.Geospatial地理位置

Redis通過Geospatial可以根據地理位置如經度、緯度查詢出兩地之間的距離。主要分為以下幾個指令:

①geoadd:

# 添加規則:除兩極不能添加外,其它均能添加
# 參數 key 經度 緯度 名稱
# 有效的經度從-180度到180度
# 有效的緯度從-85.05112878度到85.05112878度      
127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing
(integer) 1127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai  # 添加地理位置
(integer) 1127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqi 114.05 22.52 shengzhen
(integer) 2127.0.0.1:6379> geoadd china:city 120.16 30.24 hangzhou 108.96 34.26 xian
(integer) 2      

②geopos:

127.0.0.1:6379> geopos china:city beijing   # 擷取指定的成員的經度和緯度1) 1) "116.39999896287918091"
   2) "39.90000009167092543"127.0.0.1:6379> geopos china:city beijing xian1) 1) "116.39999896287918091"
   2) "39.90000009167092543"2) 1) "108.96000176668167114"
   2) "34.25999964418929977"      

③geodist:

計算兩個城市地區之間的直線距離:

  • m表示機關米
  • km表示機關千米
  • mi表示機關英裡
  • ft表示機關英尺
127.0.0.1:6379> geodist china:city beijing shanghai"1067378.7564"127.0.0.1:6379> geodist china:city beijing shanghai km  # 查找北京到上海的直線距離,機關km"1067.3788"127.0.0.1:6379> geodist china:city beijing hangzhou km"1127.3378"      

④georadius:

以給定的經緯度為中心,找出某一半徑内的元素:

127.0.0.1:6379> GEORADIUS china:city 110.35 30.39 1000 km   #擷取目前經度緯度下1000km以内的城市1) "chongqi"2) "xian"3) "shengzhen"4) "hangzhou"127.0.0.1:6379> GEORADIUS china:city 110.35 30.39 500 km1) "chongqi"2) "xian"127.0.0.1:6379> GEORADIUS china:city 110.35 30.39 500 km withdist  #擷取該經度緯度下500km以内的城市并附帶距離1) 1) "chongqi"
   2) "383.1094"2) 1) "xian"
   2) "449.8190"127.0.0.1:6379> GEORADIUS china:city 110.35 30.39 500 km withcoord  #擷取該經度緯度下500km以内的城市病顯示城市的經度、緯度1) 1) "chongqi"
   2) 1) "106.49999767541885376"  2) "29.52999957900659211"2) 1) "xian"
   2) 1) "108.96000176668167114"  2) "34.25999964418929977"127.0.0.1:6379> GEORADIUS china:city 110.35 30.39 500 km withdist withcoord count 2  #count 2表示隻顯示2個1) 1) "chongqi"
   2) "383.1094"
   3) 1) "106.49999767541885376"  2) "29.52999957900659211"2) 1) "xian"
   2) "449.8190"
   3) 1) "108.96000176668167114"  2) "34.25999964418929977"      

⑤georadiusbymember:

127.0.0.1:6379> GEORADIUSBYMEMBER china:city shanghai 400 km  #以城市為中心查詢出距離400km的城市1) "hangzhou"2) "shanghai"      

⑥geohash:

該指令将傳回11個字元的geohash字元串

127.0.0.1:6379> geohash china:city beijing chongqi1) "wx4fbxxfke0"2) "wm5xzrybty0"      

⑦zset指令删除:

geo底層就是zset,是以我們可以使用zset進行删除:

127.0.0.1:6379> ZRANGE china:city 0 -11) "chongqi"2) "xian"3) "shengzhen"4) "hangzhou"5) "shanghai"6) "beijing"127.0.0.1:6379> ZREM china:city beijing
(integer) 1      

2.2.hyperloglogs

Redis基于hyperloglogs提供了一種更高效的算法來計算兩個集合中的元素個數,重複個數不累計。

這種高效率的算法替代了傳統使用set集合進行不重複元素的存取計算方式。

hyperloglogs的優點:

  • 占用記憶體小,存取2^64的不同元素的基數,隻需要12kb的記憶體存儲空間
127.0.0.1:6379> PFADD mykey a b c d e f g h i j
(integer) 1127.0.0.1:6379> PFCOUNT mykey
(integer) 10127.0.0.1:6379> PFADD mykey2 i j z x c a b n m
(integer) 1127.0.0.1:6379> PFCOUNT mykey2
(integer) 9127.0.0.1:6379> PFMERGE mykey3 mykey mykey2  #合并兩個集合的元素
OK127.0.0.1:6379> PFCOUNT mykey3  #計算元素的個數,不重複
(integer) 14      

注意:使用hyperloglogs有0.81%的錯誤率,如果不允許容錯,需要精确計算的,則不能使用hyoerloglogs。

2.3.Bitmaps類型

Bitmaps使用位0 1進行資料的存儲。

适用場景:統計使用者資訊,活躍與非活躍、登入、打卡

127.0.0.1:6379> setbit sign 0 1(integer) 0127.0.0.1:6379> setbit sign 1 0(integer) 0127.0.0.1:6379> setbit sign 2 0(integer) 0127.0.0.1:6379> setbit sign 3 1(integer) 0127.0.0.1:6379> setbit sign 4 1(integer) 0127.0.0.1:6379> setbit sign 5 0(integer) 0127.0.0.1:6379> setbit sign 6 0(integer) 0127.0.0.1:6379> getbit sign 3  #檢視某一天是否有打卡(integer) 1127.0.0.1:6379> getbit sign 6(integer) 0      

繼續閱讀