redis五大數據類型 hdx 一、5大基礎類型 二、3大特殊類型 三、事務 四、jedis

一、5大基礎類型

1. 基本命令

keys *          #查看當前庫所有k
set k v         #設置k, v
get k           #獲取k
expire k 10     #設置key過期時間  單位秒
ttl k           #查看k的剩餘時間
select 0        #切換數據庫 0/16 默認16個庫 配置文件中配置
flushdb         #清空當前庫k
flushall        #清空所有庫k
move k          #移除k
exists k,k1     #查詢k是否存在
type k          #查詢k對應的v存儲類型

2. String類型

append k v          #追加字符串,如果k不存在就相當添加
strlen k            #獲取字符串長度
-----------------------------
incr k              #原子加1
decr k              #原子減1
incrby k 10         #原子加10  10是步長 可用在瀏覽量
decrby k 10         #原子減10  10是步長   
-----------------------------
getrange k 0 3      #截取字符串 從0位置-3位置 4個字符串
getrange k 0 -1     #去字符串所有內容
-----------------------------
setrange k 1 xxx    #從下標位1開始替換後面的內容
-----------------------------
setex k v 60        #設置k,v,過期時間
-----------------------------
setnx k v           #k不存在再設置值(常在分佈式鎖中使用)
-----------------------------
mset k1 v1 k2 v2 k3 v3  #批量設置k,v
msetnx k1 v1 k4 v4      #存在的key,值就不設置了
mget k1 k2 k3           #獲取多個key值
-----------------------------
getset k v              #先獲取在設置, CAS 原子操作
e.g
114.116.230.154:6397> getset db redis
(nil)
114.116.230.154:6397> get db
"redis"
114.116.230.154:6397> getset db mongodb
"redis"
114.116.230.154:6397> get db
"mongodb"

3. List

list 可以用來實現隊列、棧,所有的命令都是以==L==開頭。

#從左向右添加數據,如果集合不存在創建集合
114.116.230.154:6397> lpush list one    #lpush:從左向右添加,後添加的總是在頭部0的位置(棧)
(integer) 1
114.116.230.154:6397> lpush list two
(integer) 2
114.116.230.154:6397> lpush list three
(integer) 3
114.116.230.154:6397> lrange list 0 -1  #獲取list中的所有值
1) "three"
2) "two"
3) "one"
114.116.230.154:6397> lrange list 0 1   #獲取list中的區間值,如果獲取第一個值 lrange list 0 0
1) "three"
2) "two"
------------------------------------------
#從右向左添加數據,如集合不存在添加集合
114.116.230.154:6397> rpush list right  #rpush:從右向左添加
(integer) 4
114.116.230.154:6397> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
------------------------------------------
#從左邊或者右邊彈出元素
114.116.230.154:6397> lrange list  0 -1
1) "three"
2) "two"
3) "one"
4) "right"
114.116.230.154:6397> lpop list     #彈出左邊第一個元素,並移除
"three"
114.116.230.154:6397> lrange list 0 -1
1) "two"
2) "one"
3) "right"
114.116.230.154:6397> rpop list     #彈出右邊第一個元素,並移除
"right"
114.116.230.154:6397> lrange list 0 -1
1) "two"
2) "one"
# lpush + lpop(棧),lpush + rpop(隊列)
-----------------------------------------
#獲取集合中指定下標元素
114.116.230.154:6397> lrange list 0 -1  #展示list集合中所有元素
1) "two"
2) "one"
114.116.230.154:6397> lindex list 0     #根據list集合下標獲取集合元素
"two"
114.116.230.154:6397> lindex list 1
"one"
-----------------------------------------
#獲取集合長度
114.116.230.154:6397> lrange list 0 -1
1) "two"
2) "one"
114.116.230.154:6397> llen list         #獲取list集合長度
(integer) 2
-----------------------------------------
#移除集合中的指定元素值,並指定移除幾個
114.116.230.154:6397> lpush list one two three three    #從左向右添加值
(integer) 4
114.116.230.154:6397> lrange list 0 -1
1) "three"
2) "three"
3) "two"
4) "one"
114.116.230.154:6397> lrem list 1 one   #移除指定值one,並移除1個
(integer) 1
114.116.230.154:6397> lrange list 0 -1
1) "three"
2) "three"
3) "two"
(0.53s)
114.116.230.154:6397> lrem list 3 three #移除指定值three,並移除3個,但實際就2個所以都移除了。
(integer) 2
114.116.230.154:6397> lrange list 0 -1
1) "two"
---------------------------------------
#結合修剪,截取指定下標 n~m 的元素包含n,m的內容
114.116.230.154:6397> lrange mylist 0 -1
1) "h5"
2) "h4"
3) "h3"
4) "h2"
5) "h1"
114.116.230.154:6397> ltrim mylist 1 3  #ltrim:集合修剪操作,只保留下標1~3的元素
OK
114.116.230.154:6397> lrange mylist 0 -1
1) "h4"
2) "h3"
3) "h2"
---------------------------------------
#將一個集合的最後一個元素pop,push到另一個集合中
114.116.230.154:6397> lrange mylist 0 -1
1) "h6"
2) "h5"
3) "h4"
4) "h3"
5) "h2"
114.116.230.154:6397> rpoplpush mylist newlist #從mylist最後一個元素移除,到新列表newlist
"h2"
114.116.230.154:6397> lrange newlist 0 -1
1) "h2"
114.116.230.154:6397> lrange mylist 0 -1
1) "h6"
2) "h5"
3) "h4"
4) "h3"
---------------------------------------
#指定下標賦值
114.116.230.154:6397> lrange mylist 0 -1
1) "h6"
2) "h5"
3) "h4"
4) "h3"
114.116.230.154:6397> lset list 0 hdx   #指定下標賦值list不存在報錯,所以先lpush或rpush
(error) ERR no such key
114.116.230.154:6397> lset mylist 1 h7  #向mylist集合的下標 1 處賦值 h7, 如下標不存在也會報錯
OK
114.116.230.154:6397> lrange mylist 0 -1    #結果原下標 1 處的 h5 被覆蓋
1) "h6"
2) "h7"
3) "h4"
4) "h3"
---------------------------------------
#指定內容元素前or後插入新元素
114.116.230.154:6397> lrange mylist 0 -1
1) "h6"
2) "h7"
3) "h4"
4) "h3"
114.116.230.154:6397> linsert mylist before h7 hdx  #向mylist集合中h7元素前面插入hdx元素
(integer) 5
114.116.230.154:6397> lrange mylist 0 -1
1) "h6"
2) "hdx"
3) "h7"
4) "h4"
5) "h3"
# 操作類似一個連表 [before] Node [after] 

小結

底層實現相當一個連表,比如lpush是向頭節點插入數據,rpush是向尾節點插入數據。可以向某個具體節點插入數據 比如 linsert。

可用用作隊列,棧

4. set

set值是不能重複的,set的命令都是==S==開頭

#set的基本操作
114.116.230.154:6397> sadd myset hello  #向myset集合中set值
(integer) 1
114.116.230.154:6397> sadd myset hdx
(integer) 1
114.116.230.154:6397> smembers myset    #展示myset集合中所有值
1) "hdx"
2) "hello"
114.116.230.154:6397> sismember myset hdx   #查詢某個值(hdx),是否存在集合中,存在返回1
(integer) 1
---------------------------------------
#獲取set集合元素個數
114.116.230.154:6397> smembers myset
1) "hdx"
2) "hello"
114.116.230.154:6397> scard myset   #查看set集合元素個數
(integer) 2
---------------------------------------
#移除set集合元素
114.116.230.154:6397> smembers myset    #展示set集合中的元素[hdx, hello]
1) "hdx"
2) "hello"
114.116.230.154:6397> srem myset hdx    #移除set集合中的hdx元素
(integer) 1
114.116.230.154:6397> scard myset   #查詢set集合中元素個數
(integer) 1
114.116.230.154:6397> smembers myset    #展示set集合中全部元素,只剩下hello
1) "hello"
----------------------------------------
#從set集合中隨機獲取指定個數元素
114.116.230.154:6397> sadd myset a b c d e f g  #向set集合中添加7個元素
(integer) 7
114.116.230.154:6397> smembers myset    #展示set集合中所用元素
1) "d"
2) "c"
3) "a"
4) "g"
5) "f"
6) "e"
7) "b"
114.116.230.154:6397> srandmember myset 1   #隨機獲取 1 個元素
1) "b"
114.116.230.154:6397> srandmember myset 2   #隨機獲取 2 個元素
1) "a"
2) "g"

#實現抽獎需求
----------------------------------------
#將一個元素從一個集合移動到另一個集合
114.116.230.154:6397> smembers myset
1) "a"
2) "g"
3) "f"
4) "c"
5) "d"
6) "e"
7) "b"
114.116.230.154:6397> smove myset newset a  #將myset集合中的a元素移動到newset集合中
(integer) 1
114.116.230.154:6397> smembers newset
1) "a"
114.116.230.154:6397> smembers myset
1) "g"
2) "f"
3) "c"
4) "d"
5) "e"
6) "b"
---------------------------------------
#差集
#交集
#並集

#差集
114.116.230.154:6397> smembers myset    #myset集合元素
1) "g"
2) "f"
3) "c"
4) "d"
5) "e"
6) "b"
114.116.230.154:6397> smembers newset   #newset集合元素
1) "a"
2) "x"
3) "y"
4) "b"
5) "z"
114.116.230.154:6397> sdiff myset newset  #myset與newset的差集(myset中哪些元素是newset沒有的,比如 b元素 )
1) "f"
2) "g"
3) "d"
4) "c"
5) "e"

114.116.230.154:6397> sdiff newset myset  #newset與myset的差集(newset中哪些元素是myset中沒有的,比如 b元素)
1) "y"
2) "x"
3) "a"
4) "z"
#根據 myset,newset的順序不同,結果集也不同。
-----------------------------
#交集
114.116.230.154:6397> smembers myset
1) "g"
2) "f"
3) "c"
4) "d"
5) "e"
6) "b"
114.116.230.154:6397> smembers newset
1) "a"
2) "x"
3) "y"
4) "b"
5) "z"
114.116.230.154:6397> sinter myset newset   #myset與newset的交集 b
1) "b"
114.116.230.154:6397> sinter newset myset   #newset與myset的交集 b 
1) "b"
#找出兩個集合共有的元素
-----------------------------
#並集
114.116.230.154:6397> smembers myset
1) "g"
2) "f"
3) "c"
4) "d"
5) "e"
6) "b"
114.116.230.154:6397> smembers newset
1) "a"
2) "x"
3) "y"
4) "b"
5) "z"
114.116.230.154:6397> SUNION myset newset   #myset 與newset的並集
 1) "c"
 2) "d"
 3) "e"
 4) "b"
 5) "a"
 6) "f"
 7) "g"
 8) "y"
 9) "x"
10) "z"
#相當兩個集合元素去重

5. hash

String數據類型是key:value

hash數據類型是 key : (k:v),也可以理解成一對對象裏面有多個屬性。hash命令是以==h==開頭。

#hash 的形式
114.116.230.154:6397> hset myhash filed1 hdx    #向myhash中設置一個鍵值對 k是field1,v是hdx
(integer) 1
114.116.230.154:6397> hget myhash filed1    #獲取myhash中field1屬性的值
"hdx"
114.116.230.154:6397> hmset myhash field1 hello field2 world #hmset向myhash中設置多個鍵值
OK
114.116.230.154:6397> hmget myhash field1 field2 #hmget 通過多個鍵從myhash中取出多個值
1) "hello"
2) "world"
114.116.230.154:6397> hgetall myhash    #取出myhash的所有鍵和值
1) "filed1" #鍵
2) "hdx"    #值
3) "field1" #鍵
4) "hello"  #值
5) "field2" #鍵
6) "world"  #值
114.116.230.154:6397> hkeys myhash  #獲取myhahs中所有的key
1) "filed1"
2) "field2"
114.116.230.154:6397> hvals myhash  #獲取myhash中所有的value
1) "hdx"
2) "world"
-----------------------------------
114.116.230.154:6397> hgetall myhash
1) "filed1" #鍵
2) "hdx"    #值
3) "field2" #鍵
4) "world"  #值
114.116.230.154:6397> hlen myhash   #獲取myhash中的長度,結果證明是鍵值對的個數。
(integer) 2
-----------------------------------
114.116.230.154:6397> hgetall myhash
1) "filed1"
2) "hdx"
3) "field2"
4) "world"
114.116.230.154:6397> hexists myhash field2 #判斷 myhash中field2屬性是否存在
(integer) 1
-----------------------------------
114.116.230.154:6397> hset myhash field3 5  
(integer) 1
114.116.230.154:6397> hincrby myhahs field3 1   #field3屬性自增 1
(integer) 1
114.116.230.154:6397> hincrby myhash field3 -1  #field3屬性自減 1
(integer) 4

hash數據類型可以用於對象的存儲,而string只適合簡單的字符串存儲。

6. zset

zset 命令與set類似,zset命令以==z==開頭,zset是有序的集合,只支持最小值到最大值排序。

114.116.230.154:6397> zadd salary 500 hdx
(integer) 1
114.116.230.154:6397> zadd salary 1500 haha
(integer) 1
114.116.230.154:6397> zadd salary 2500 sanmao
(integer) 1
114.116.230.154:6397> zrangebyscore salary -inf +inf
1) "hdx"
2) "haha"
3) "sanmao"
114.116.230.154:6397> zrangebyscore salary +inf -inf    #不支持
(empty list or set)
----------------------------------------
114.116.230.154:6397> zrange salary 0 -1    #查詢所有key
1) "hdx"
2) "haha"
3) "sanmao"
114.116.230.154:6397> zrem salary sanmao    #移除sanmao元素
(integer) 1
114.116.230.154:6397> zrange salary 0 -1
1) "hdx"
2) "haha"
----------------------------------------
114.116.230.154:6397> zcard salary      #查看個數
(integer) 2

二、3大特殊類型

1. geospatial 地理空間

朋友定位,附近的人,打車

#添加城市經緯度 前面是精度[-180~180] 緯度[-85~85]
114.116.230.154:6397> geoadd china:city 116.40 39.91 beijing
(integer) 1
114.116.230.154:6397> geoadd china:city 121.47 31.23 shanghai
(integer) 1
114.116.230.154:6397> geoadd china:city 106.50 29.53 chongqing
(integer) 1
114.116.230.154:6397> geoadd china:city 114.05 22.52 shenzhen
(integer) 1
114.116.230.154:6397> geoadd china:city 120.16 30.24 hangzhou
(integer) 1
114.116.230.154:6397> geoadd china:city 108.96 34.26 xian
(integer) 1
---------------------------------
#geopos 獲取城市北京經緯度
114.116.230.154:6397> geopos china:city beijing 
1) "116.39999896287918"
2) "39.909999566644508"
---------------------------------
#geopos兩個城市之間的直線距離
114.116.230.154:6397> geopos china:city beijing
1) 1) "116.39999896287918"
   2) "39.909999566644508"
114.116.230.154:6397> geodist china:city beijing shanghai
"1068370.2525"
(1.72s)
114.116.230.154:6397> geodist china:city beijing shanghai km
"1068.3703"
---------------------------------
#georadius附近的人,給出一個精度查詢半徑之內的值
114.116.230.154:6397> georadius china:city 110 30 500 km
1) "chongqing"
2) "xian"
#精度110緯度30 半徑500千米以內的城市
-----------------
#精度110緯度30 半徑500千米以內的城市,並顯示直線距離withdist,經緯度withcoord,查詢個數count
114.116.230.154:6397> georadius china:city 110 30 500 km withcoord withdist count 1
1) 1) "chongqing"
   2) "341.9374"
   3) 1) "106.49999767541885"
      2) "29.529999579006592"
------------------
#查詢某個城市(key)的半徑400千米的城市
114.116.230.154:6397> georadiusbymember china:city hangzhou 400 km
1) "hangzhou"
2) "shanghai"
------------------
#geospatial底層是通過zset實現的,所以移除元素可以是用zrem
114.116.230.154:6397> zrange china:city 0 -1
1) "chongqing"
2) "xian"
3) "shenzhen"
4) "hangzhou"
5) "shanghai"
6) "beijing"
114.116.230.154:6397> zrem china:city xian
(integer) 1
114.116.230.154:6397> zrange china:city 0 -1
1) "chongqing"
2) "shenzhen"
3) "hangzhou"
4) "shanghai"
5) "beijing"

2. hyperloglog

是什麼?是兩個set集合去重合並返回元素數量。官方0.81%錯誤率,如果允許誤差建議使用,效率高節省空間。如果不允許誤差那麼不建議使用。

114.116.230.154:6397> pfadd mykey a b c d e f g h i j   #添加不可重複的元素集合
(integer) 1
114.116.230.154:6397> pfcount mykey #獲取元素數量
(integer) 10
114.116.230.154:6397> pfadd mykey2 i j z x c v b n m
(integer) 1
114.116.230.154:6397> pfcount mykey
(integer) 10
114.116.230.154:6397> pfmerge mykey3 mykey mykey2   #合併mykye和mykey2元素,結果存到mykey3中
OK
114.116.230.154:6397> pfcount mykey3    #mykey3數量15,將兩個集合去重合並統計數值
(integer) 15

3. bitmaps

位存儲,記錄0,1狀態

114.116.230.154:6397> setbit sign 0 1   #
(integer) 0
114.116.230.154:6397> setbit sign 1 0
(integer) 0
114.116.230.154:6397> setbit sign 2 0
(integer) 0
114.116.230.154:6397> setbit sign 3 1
(integer) 0
114.116.230.154:6397> setbit sign 4 1
(integer) 0
114.116.230.154:6397> setbit sign 5 0
(integer) 0
114.116.230.154:6397> setbit sign 6 0
(integer) 0
114.116.230.154:6397> getbit sign 3     #獲取到sign裏面3 的狀態
(integer) 1
114.116.230.154:6397> getbit sign 6     #獲取到sign裏面6 的狀態
(integer) 0
114.116.230.154:6397> bitcount sign     #獲取到sign裏面狀態爲1的個數
(integer) 3

三、事務

1.redis事務特性

redis的事務是不保證原子性的(redis單條命令是保證原子性的)

redis 事務沒有隔離級別概念

redis事務的特性:一次性、順序性、排他性

redis事務:

開啓事務(multi) -> 命令入隊(...) -> 執行事務(exec)

2.redis事務基本操作

#正常開啓事務執行事務
114.116.230.154:6397> multi     #開啓事務
OK
114.116.230.154:6397> set k1 v1
QUEUED
114.116.230.154:6397> set k2 v2
QUEUED
114.116.230.154:6397> get k2
QUEUED
114.116.230.154:6397> set k3 v3
QUEUED
114.116.230.154:6397> exec      #執行隊列,並結束事務
1) OK
2) OK
3) "v2"
4) OK
-----------------------
114.116.230.154:6397> multi
OK
114.116.230.154:6397> set k1 v1
QUEUED
114.116.230.154:6397> set k2 v2
QUEUED
114.116.230.154:6397> set k4 v4
QUEUED
114.116.230.154:6397> discard   #取消事務,入隊的命令都不會執行
OK
114.116.230.154:6397> get k4
(nil)

3.事務錯誤異常情況

類比編譯時異常:就是語法或命令錯誤導致的無法編譯或執行,這類的異常在redis事務中是不會被執行的。

114.116.230.154:6397> multi
OK
114.116.230.154:6397> set k1 v1
QUEUED
114.116.230.154:6397> set k2 v2
QUEUED
114.116.230.154:6397> set k3 v3
QUEUED
114.116.230.154:6397> getset k3
(error) ERR wrong number of arguments for 'getset' command
114.116.230.154:6397> set k4 v4
QUEUED
114.116.230.154:6397> set k5 v5
QUEUED
114.116.230.154:6397> exec
(error) EXECABORT Transaction discarded because of previous errors.

運行時異常:編譯器在編譯的時候無法發現錯誤,只有在程序運行過程中產生的錯誤。這類錯誤redis事務中是會被執行的。

114.116.230.154:6397> multi
OK
114.116.230.154:6397> set k1 v1
QUEUED
114.116.230.154:6397> incr k1
QUEUED
114.116.230.154:6397> set k2 v2
QUEUED
114.116.230.154:6397> get k2
QUEUED
114.116.230.154:6397> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
4) "v2"
114.116.230.154:6397> get k1
"v1"
114.116.230.154:6397> get k2
"v2"

4.事務監控

監控:watch -- 樂觀鎖

#正常執成功,事務正常結束,事務期間沒有發生任何錯誤
114.116.230.154:6397> set money 100
OK
114.116.230.154:6397> set out 0
OK
114.116.230.154:6397> watch money   #監視money值(樂觀鎖)
OK
114.116.230.154:6397> multi
OK
114.116.230.154:6397> decrby money 20
QUEUED
114.116.230.154:6397> incrby out 20
QUEUED
114.116.230.154:6397> exec
1) (integer) 80
2) (integer) 20

多線程演示 watch

#第一個線程操作
114.116.230.154:6397> watch money   #監視money
OK
114.116.230.154:6397> multi #開啓事務
OK
114.116.230.154:6397> decrby money 20
QUEUED
114.116.230.154:6397> incrby out 20
QUEUED
#第二個線程操作
114.116.230.154:6397> decrby money 10   #減掉10塊
(integer) 70
#第一個線程操作
114.116.230.154:6397> exec  #第一個線程執行事務不成功
(nil)
#第一線程操作失敗之後可以繼續操作
114.116.230.154:6397> unwatch   #接觸監控
OK
114.116.230.154:6397> watch money   #重新獲取監控
OK
114.116.230.154:6397> multi     #開啓事務繼續執行後續命令
OK
114.116.230.154:6397> decrby mone 20
QUEUED
114.116.230.154:6397> incrby out 20
QUEUED
114.116.230.154:6397> exec
1) (integer) -20
2) (integer) 40

監控總結:money值通過 watch監視,如果在一個線程事務中正在執行還未提交,那麼被監視的對象被另外一個線程修改了,再提交事務的時候會失敗。這種機制符合樂觀鎖機制,認爲什麼時候值都不會被改變,之後在提交事務的時候去判斷值是否與之前一致,一致成功反之失敗。經典cas原理。

如果是悲觀鎖:那麼就是money這個值認爲什麼時候都有可能被修改,加鎖之後只有當前加鎖線程可以操作money。其他線程只有等待money鎖釋放後才能操作。

所以在上面的例子中redis的監控(watch)機制顯然是樂觀鎖機制。

四、jedis

p23

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章