Redis系列四:redis支持的数据类型
一、字符串<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<哈希表>
當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. 用來存儲多個有序的字符串,一個列表最多可存2的32次方減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 //索引下標特點:從左到右為0到N-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個,
若lrem test 8 b, 刪除8個b, 但只有5個全部刪除
?lrange test 0 -1 //刪除后的結果為 b j x z
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內部編碼,它結合了ziplist和linkedlist兩者的優勢,之前的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//1和2差集,(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_jj:4james(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編碼,可有效減少內存的使用
2.skiplist:
zadd user:10 20 james......
//大于128個元素或元素值大于64字節時為skiplist編碼
3.使用場景:
???排行榜系統,如視頻網站需要對用戶上傳的視頻做排行榜
???點贊數:zadd user:1:20180106 3 mike ?//mike獲得3個贊
???再獲一贊:zincrby user:1:20180106 1 mike ?//在3的基礎上加1
???用戶作弊,將用戶從排行榜刪掉:zrem user:1:20180106 mike
???展示贊數最多的5個用戶:zrevrangebyrank user:1:20180106 ?0 ?4
???查看用戶贊數與排名:
????zscore user:1:20180106 mike ??zrank user:1:20180106 mike
?
轉載于:https://www.cnblogs.com/leeSmall/p/8344955.html
總結
以上是生活随笔為你收集整理的Redis系列四:redis支持的数据类型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 七周三次课(1月24日) 10.11 L
- 下一篇: LeetCode-35. Search