1. 程式人生 > >Redis系列四:redis支援的資料型別

Redis系列四:redis支援的資料型別

轉自 http://www.cnblogs.com/leeSmall/p/8344955.html

一、字串<String>

 1. 字串型別:實際上可以是字串(包括XML JSON),還有數字(整形 浮點數),二進位制(圖片 音訊 視訊),最大不能超過512MB

 2. 設值命令:

set name lgs ex 10  //10秒後過期  px 10000 毫秒過期

setnx name lgs       //不存在鍵name時才能設定,返回1設定成功;存在的話失敗0

set age 29             //存在鍵age時直接覆蓋之前的鍵值,返回1成功

場景:如果有多客戶同時執行setnx,只有一個能設定成功,可做分散式鎖

獲值命令:get age   //存在則返回value, 不存在返回nil

批量設值:mset country china city beijing

批量獲取:mget country city address     //返回china  beigjin, address為nil   

若沒有mget命令,則要執行n次get命令,從而佔用網路資源影響效能

使用 mget= 1次網路請求+redis內部n次查詢,一次性返回所有查詢結果

3. 計數:

incr age      //必須為整數自加1,非整數返回錯誤,無age鍵從0自增返回1

decr age    //整數age減1,非整數返回錯誤,無age鍵從0自減返回-1

incrby age 2  //整數age+2

decrby age 2//整數age -2

incrbyfloat age 1.1 //整數age+1.1

4. append追加指令:set name hello; append name world //追加後成helloworld

5. 字串長度:set hello “世界”;strlen hello //結果6,每個中文佔3個位元組

6. 擷取字串:set name helloworld ; getrange name 2 4//返回 llo

7. 內部編碼:

int:8位元組長整型

  set age 100; object encoding age    //返回int

embstr:小於等於39位元組串

  set name bejin;

      object encodeing name  //返回embstr

raw:大於39位元組的字串

  set a fsdfwerwerweffffffffffdfsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

  object encoding a //返回raw

8. 切換資料庫:select 2

9. 應用場景:

鍵值設計:業務名:物件名:id:[屬性]

資料庫為order, 使用者表user,對應的鍵可為 order:user:1 或order:user:1:name

注意:redis目前處於受保護模式,不允許非本地客戶端連結,可以通過給redis設定密碼,然後客戶端連結的時候,寫上密碼就可以了

     127.0.0.1:6379> config set requirepass 123456  臨時生效

   或者修改redis.conf   requirepass 123456,

   啟動時./redis-server redis.conf指定conf

          ./redis-cli -p 6379 -a 12345678  //需要加入密碼才能訪問

二、雜湊hash

雜湊hash是一個string型別的field和value的對映表,hash適合用於儲存物件

1. 命令  hset key field value

   設值:hset user:1 name lgs         //成功返回1,失敗返回0

   取值:hget user:1 name              //返回lgs

   刪值:hdel user:1 age                //返回刪除的個數

   計算鍵對應的欄位個數:

 hset user:1 name lgs; hset user:1 age 27;

   hlen user:1               //返回2,user:1有兩個屬性值

   批量設值:hmset user:2 name ll age 28 sex boy //返回OK

   批量取值:hmget user:2 name age sex   //返回三行:ll 28 boy

   判斷field是否存在:hexists user:2 name  //若存在返回1,不存在返回0

   獲取所有field: hkeys user:2                  // 返回name age sex三個field

   獲取user:2所有value:hvals user:2        // 返回ll 28 boy

   獲取user:2所有field與value:hgetall user:2 //name age sex ll 28 boy值

   增加1:

 hincrby user:2 age 1      //age+1

   hincrbyfloat user:2 age 2   //浮點型加2

2. 內部編碼:ziplist<壓縮列表>和hashtable<雜湊表>

  redis初始建立hash表,有序集合,連結串列時, 儲存結構採用一種ziplist的儲存結構, 這種結構記憶體排列更緊密, 能提高訪存效能.

    當field個數少且沒有大的value時,內部編碼為ziplist

  如:hmset user:3 name lgs age 27; object encoding user:3 //返回ziplist

當value大於64位元組,內部編碼由ziplist變成hashtable

    如:hset user:4 address “a64位元組”; object encoding user:3 //返回hashtable

    HASH型別是稀疏,每個鍵可以有不同的filed, 若用redis模擬做關係複雜查詢開發因難,維護成本高

3. 三種方案實現使用者資訊儲存優缺點:

   1. 原生:

    set user:1:name james;

         set user:1:age  23;

         set user:1:sex boy;

      優點:簡單直觀,每個鍵對應一個值

      缺點:鍵數過多,佔用記憶體多,使用者資訊過於分散,不用於生產環境

  2. 將物件序列化存入redis

    set user:1 serialize(userInfo);

        優點:程式設計簡單,若使用序列化合理記憶體使用率高

        缺點:序列化與反序列化有一定開銷,更新屬性時需要把userInfo全取出來進行反序列化,更新後再序列化到redis

  3. 使用hash型別:

        hmset user:1 name james age 23 sex boy

   優點:簡單直觀,使用合理可減少記憶體空間消耗

   缺點:要控制ziplist與hashtable兩種編碼轉換,且hashtable會消耗更多記憶體

總結:對於更新不多的情況下,可以使用序列化,對於VALUE值不大於64位元組可以使用hash型別

4. 應用場景

資料庫有張使用者表結構如下:

使用hash轉存

三、列表<list>

1. 用來儲存多個有序的字串,一個列表最多可存232次方減1個元素;

因為有序,可以通過索引下標獲取元素或某個範圍內元素列表, 列表元素可以重複

 

 2. 列表相關命令 

新增命令:rpush lpush linset

rpush name a b c d    //從右向左插入a b c d返回值4

lrange name  0 -1      //從左到右獲取列表所有元素 返回 a b c d

lpush fav a b c d       //從左向右插入a b c d

linsert fav before b r //b之前插入r, after為之後,使 lrange fav 0 -1 檢視:d c r b a

查詢命令:lrange lindex llen

lrange key start end //索引下標特點:從左到右為0N-1

lindex fav -1 //返回最右末尾a-2返回b

llen fav //返回當前列表長度 5

刪除命令:lpop rpop lrem ltrim

lpop fav //把最左邊的第一個元素d刪除

rpop fav //把最右邊的元素a刪除

lrem key count value//刪除指定元素

如:lpush test b b b b b j x z //test放入z x j b b b b b

Lrange test 0 -1 //查詢結果為 z x j b b b b b

lrem test 4 b      //從左右開始刪除b的元素,刪除4個, lrange test 0 -1 //刪除後的結果為 b j x z

lrem test 8 b, 刪除8b, 但只有5個全部刪除,lrem test 0 b  //檢索所有b全部刪除 j x z 

lpush user b b b b b j x z //user從左到右放入 z x j b b b b b

ltrim user 1 3  //只保留從第2到第4的元素x j b,其它全刪

lrange user 0 -1 //查詢結果為 x j b, 其它已全被刪掉

修改命令:lset

lpush user01 z y x //user01從左到右放入x y z

lset user01 2 java // 把第3個元素z替換成java

lrange user01 0 -1 //查詢結果為 x y java

 阻塞命令:blpop brpop

3.列表內部編碼

1當元素個數少且沒大元素,編碼為ziplist,減少記憶體的使用

   rpush list a b c

   object encoding list //返回ziplist

2當元素超過512個,或元素超過64位元組,內部編碼變成linkedlist連結串列;

   rpush list a1 a2 ....a513  rpush list xxxxxxxxxxxxxx

   object encoding list  //linkedlist

3.2版本以後,redis提供了quicklist內部編碼,它結合了ziplistlinkedlist兩者的優勢,之前的ziplist是存在BUG的,使用quicklist內部編碼效率更高,所以我們現在3.2以後看不到這兩個編碼,只看到quicklist, 

4. 列表應用場景

以訂單為例子(不推薦使用redis做訊息佇列)

1.每個使用者有多個訂單key為 order:1   order:2  order:3, 結合hmset

  hmset order:1 orderId 1 money 36.6 time 2018-01-01

  hmset order:2 orderId 2 money 38.6 time 2018-01-01

  hmset order:3 orderId 3 money 39.6 time 2018-01-01

  把訂單資訊的key放到佇列

  lpush user:1:order order:1 order:2 order:3

   每新產生一個訂單,

   hmset order:4 orderId 4 money 40.6 time 2018-01-01

追加一個order:4放入佇列第一個位置

   lpush user:1:order order:4

 當需要查詢使用者訂單記錄時:

 List orderKeys = lrange user:1 0 -1 //查詢user:1 的所有訂單key

  for(Order order: orderKeys){

           hmget order:1

}

四、無序集合set

儲存多元素,與列表不一樣的是不允許有重複元素,且集合是無序,一個集合最多可存2的32次方減1個元素,除了支援增刪改查,還支援集合交集、並集、差集;

1. 無序集合set相關命令

元素操作:exists sadd smembers srem scard spop

exists user        //檢查user鍵值是否存在
sadd user a b c //向user插入3個元素,返回3
sadd user a b   //若再加入相同的元素,則重複無效,返回0
smembers user //獲取user的所有元素,返回結果無序
srem user a     //返回1,刪除a元素
scard user      //返回2,計算元素個數

sismember user a     //判斷元素是否在集合存在,存在返回1,不存在0
srandmember user 2 //隨機返回2個元素,2為元素個數
spop user 2            //隨機返回2個元素a b,並將a b從集合中刪除
smembers user       //此時已沒有a b, 只有c

集合交集:sinter

sadd user:1 zhangsan 24 girl
sadd user:2 james 24 boy//初始化兩個集合
sinter user:1 user:2 //求兩集合交集, 此時返回24

sadd user:3 wang 24 girl //新增第三個元素
sinter user:1 user:2 user:3 //求三個集合的交集,此時返回24

集合的並集(集合合併去重):sunion

 sunion user:1 user:2 user:3   //三集合合併(並集),去重24

集合差集:sdiff

diff user:1 user:2  //12差集,(zhangsan 24 girl)-(james 24 boy)=zhangsan girl

將集合的結果另存到佇列:sinterstore sunionstore sdiffstore

將交集(jj)、並集(bj)、差集(cj)的結果儲存:
sinterstore user_jj user:1 user:2 //將user:1 user:2的交集儲存到user_jj
sunionstore user_bj user:1 user:2 //將user:1 user:2的(並)合集儲存user_bj
sdiffstore user_cj user:1 user:2 //將user:1-user:2的差集儲存user_cj
smemebers user_cj // 返回zhangsan girl

2. 內部編碼

sadd user 1 2 3 4    //當元素個數少(小於512個)且都為整數,redis使用intset 減少記憶體的使用
sadd user 1 2...513 //當超過512個或不為整數(比如a b)時,編碼為hashtable
object encoding user //hashtables

3.無序集合set的應用場景

標籤,社交,查詢有共同興趣愛好的人,智慧推薦
使用方式:
給使用者新增標籤:
sadd user:1:fav basball fball pq
sadd user:2:fav basball fball 
............

或給標籤新增使用者
sadd basball:users user:1 user:3
sadd fball:users user:1 user:2 user:3
........

計算出共同感興趣的人:
sinter user:1:fav user2:fav

五、有序集合

常用於排行榜,如視訊網站需要對使用者上傳視訊做排行榜,或點贊數

與集合有聯絡,不能有重複的成員

有序集合與集合set及佇列list區別:

1.有序集合相關命令

新增命令

zadd key score member [score member......]
zadd user:zan 200 james //james的點贊數1, 返回操作成功的條數1
zadd user:zan 200 james 120 mike 100 lee// 返回3

zadd test:1 nx 100 james            //鍵test:1必須不存在,主用於新增
zadd test:1 xx incr 200 james      //鍵test:1必須存在,主用於修改,此時為300
zadd test:1 xx ch incr -299 james //返回操作結果1,300-299=1

檢視命令

zrange test:1 0 -1 withscores  //檢視點贊(分數)與成員名
zcard test:1                           //計算成員個數, 返回1

查點贊數
zadd test:2 nx 100 james //新增一個集合
zscore test:2 james        //檢視james的點贊數(分數),返回100

排名:
zadd user:3 200 james 120 mike 100 lee//先插入資料
zrange user:3 0 -1 withscores              //檢視分數與成員

zrank user:3 james                             //返回名次:第3名返回2,從0開始到2,共3名
zrevrank user:3 james                        //返回0, 反排序,點贊數越高,排名越前

刪除命令

刪除成員:

zrem user:3 jame mike //返回成功刪除2個成員,還剩lee

增加分數:
zincrby user:3 10 lee         //成員lee的分數加10
zadd user:3 xx incr 10 lee //和上面效果一樣

返回指定排名範圍的分數與成員
zadd user:4 200 james 120 mike 100 lee//先插入資料
zrange user:4 0 -1 withscores               //返回結果如下圖

 

 zrevrange user:4 0 -1 withscores   //倒序,結果如下圖

 

返回指定分數範圍的成員
zrangebyscore user:4 110 300 withscores //返回結果如下圖, 由低到高

zrevrangebyscore user:4 300 110 withscores //返回結果如下圖,由高到低

zrangebyscore user:4 (110 +inf withscores//110到無限大,

zrevrangebyscore user:4 (110 -inf withscores//無限小到110,

 

返回指定分數範圍的成員個數:
zcount user:4 110 300 //返回2,由mike120和james200兩條資料

刪除指定排名內的升序元素:
zremrangebyrank user:4 0 1 //分數升序排列,刪除第0個與第1個,只剩james

刪除指定分數範圍的成員
zadd user:5 200 james 120 mike 100 lee//先插入測試資料
zremrangebyscore user:5 210 300 //刪除分數在210與300範圍的成員
zremrangebyscore user:5 (100 +inf //刪除分數大於100(不包括100),還剩lee

有序集合交集:

   格式:zinterstore destination numkeys key ... [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]

         destination:交集產生新的元素儲存鍵名稱

         numkeys:  要做交集計算的鍵個數

         key :元素鍵值

         weights:每個被選中的鍵對應值乘weight, 預設為1

  初始化資料:

       zadd user:7 1 james 2 mike 4 jack 5 kate      //初始化user:7資料

       zadd user:8 3 james 4 mike 4 lucy 2 lee  6 jim  //初始化user:8資料

  交集例子:

        zinterstore user_jj 2 user:7 user:8 aggregate sum //2代表鍵合併個數,

//aggregate sum可加也不可加上,因為預設是sum

//結果user_jj4james(1+3), 6mike(2+4)

zinterstore user_jjmax 2 user:7 user:8 aggregate max min

//取交集最大的分數,返回結果 3james  4mike, min取最小

 weights:

  zinterstore user_jjweight 2 user:7 user:8 weights 8 4 aggregate max

  //1,取兩個成員相同的交集,user:7->1 james  2 mike;  user:8->3 james  4 mike

  //2,user:7->james 1*8=8,  user:7->mike 2*8 =16,最後user:7結果 8 james  16 mike;

 //3,user:8-> james 3*4=12, user:8->mike 4*4=16最後user:8結果12 james  16 mike

 //4,最終相乘後的結果,取最大值為  12 james 16mike

//5, zrange user_jjweight 0 -1 withscores 查詢結果為  12 james 16mike

總結:將user:7成員值乘8,將user:8成員值乘4,取交集,取最大

有序集合並集(合併去重):

   格式:zunionstore destination numkeys key ... [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]

         destination:交集產生新的元素儲存鍵名稱

         numkeys:  要做交集計算的鍵個數

         key :元素鍵值

         weights:每個被選中的鍵對應值乘weight, 預設為1

zunionstore user_jjweight2 2 user:7 user:8 weights 8 4 aggregate max

//與以上zinterstore一樣,只是取並集,指令一樣

2.有序集合內部編碼
1. ziplist:

zadd user:9 20 james 30 mike 40 lee
object encoding user:9 //返回ziplist
//當元素個數少(小於128個),元素值小於64位元組時,使用ziplist編碼,可有效減少記憶體的使用