mutil/exec
operate big value(collection)
string
結構
key | value |
---|---|
hello | world |
counter | 1 |
bits | 101111101110 |
可以是字符串(json);數字,以及二進制
使用場景
緩存
計數器
分佈式鎖
API
命令 | 說明 | 時間複雜度 |
---|---|---|
get key | 獲取key對應的value | O(1) |
set key value | 設置key value | O(1) |
del key | 刪除key-value | O(1) |
incr | key自增1, 如果key不存在,自增後get(key) = 1 | O(1) |
decr | key自減1, 如果key不存在,自增後get(key) = -1 | O(1) |
incrby key k | key自增k, 如果key不存在,自增後get(key) = k | O(1) |
decr key k | key自減k, 如果key不存在,自增後get(key) = -k | O(1) |
set key value | 不管可以是否存在 | O(1) |
setnx key value | key不存在,才設置 | O(1) |
set key value xx | key存在,才設置 | O(1) |
mget key1 key2 key3 | 批量獲取key,原子操作 | O(N) |
mset key1 value1 key2 value2 | 批量設置key-value | O(1) |
getset key newvalue | set key newvalue並返回舊的value | O(1) |
append key value | 將value追加到舊的value | O(1) |
strlen key | 返回字符串的長度(注意中文,utf8下一個中文佔用3個字符) | O(1) |
incrbyfloat key 3.5 | 增加key對應的值3.5 | O(1) |
getrange key start end | 獲取字符串指定下標所有的值 | O(1) |
setrange key index value | 設置指定下標所有對應的值 | O(1) |
練習
127.0.0.1:6382> set hello "world" OK 127.0.0.1:6382> get hell (nil) 127.0.0.1:6382> get hello "world" 127.0.0.1:6382> del hello (integer) 1 127.0.0.1:6382> get hello (nil) 127.0.0.1:6382> get counter (nil) 127.0.0.1:6382> incr counter (integer) 1 127.0.0.1:6382> get counter "1" 127.0.0.1:6382> incrby counter 99 (integer) 100 127.0.0.1:6382> get counter "100" 127.0.0.1:6382> decr counter (integer) 99 127.0.0.1:6382> get counter "99" 127.0.0.1:6382> decrby counter 100 (integer) -1 127.0.0.1:6382> get counter "-1" 127.0.0.1:6382> exists php (integer) 0 127.0.0.1:6382> set php good OK 127.0.0.1:6382> setnx php bad (integer) 0 127.0.0.1:6382> set php best xx OK 127.0.0.1:6382> get php "best" 127.0.0.1:6382> exists java (integer) 0 127.0.0.1:6382> setnx java best (integer) 1 127.0.0.1:6382> set java easy xx OK 127.0.0.1:6382> get java "easy" 127.0.0.1:6382> set hello world OK 127.0.0.1:6382> getset hello php "world" 127.0.0.1:6382> get hello "php" 127.0.0.1:6382> append hell ",php" (integer) 4 127.0.0.1:6382> get hello "php" 127.0.0.1:6382> append hello ",php" (integer) 7 127.0.0.1:6382> get hello "php,php" 127.0.0.1:6382> strlen hello (integer) 7 127.0.0.1:6382> set hello "吳軍旗" OK 127.0.0.1:6382> strlen hello (integer) 9
n次get操作
** 1次mget操作**
實戰
記錄網站每個用戶個人主頁的訪問量
incr userid: pageview (**主要的是:單線程,所以無競爭)**)
緩存視頻的基本信息(數據源在mysql中)偽代碼
分佈式id生成器(單線程的好處)
incr id
hash
哈希鍵值結構
特點
mapmap
small redis
field不能相同,value可以相同
API
命令 | 說明 | 時間複雜度 |
---|---|---|
hget key field | 獲取hash key對應field的value | O(1) |
hset key field value | 設置has key 對應的field的value | O(1) |
hexists key field | 判斷hash key 是否有field | O(1) |
hlen key | 獲取hash key field的數量 | O(1) |
hmget key field1 field2...fieldN | 批量獲取hash key的一批field對應的值 | O(N) |
hset key field1 value1 field2 value2...fieldN valueN | 批量設置hash key的一批field value | O(1) |
hgetall key | 返回hash key對應所有的field和value | O(N) |
hvals key | 返回hash key對應所有的field的value | O(N) |
hkeys key | 返回hash key對應所有的field | O(N) |
hsetnx key field value | 設置has key 對應的field的value(如果field已經存在,則失敗) | O(1) |
hincrby key field intCounter | hash key對應的field的value自增intCounter | O(1) |
hincrbyfloat key field floatCounter | 浮點數版本 | O(1) |
注意 小心使用hgetall(牢記單線程)
練習
127.0.0.1:6382> hset user1 age 26 (integer) 1 127.0.0.1:6382> hset user1 name wujunqi (integer) 1 127.0.0.1:6382> hget all user1 (nil) 127.0.0.1:6382> hgetall user1 1) "age" 2) "26" 3) "name" 4) "wujunqi" 127.0.0.1:6382> hdel user1 age (integer) 1 127.0.0.1:6382> hgetall user1 1) "name" 2) "wujunqi" 127.0.0.1:6382> hget user1 name "wujunqi" 127.0.0.1:6382> hexists user1 name (integer) 1 127.0.0.1:6382> hlen user1 (integer) 1 127.0.0.1:6382> hmset user2 name xiaofang age 26 OK 127.0.0.1:6382> hmget user2 name age 1) "xiaofang" 2) "26" 127.0.0.1:6382> hgetall user2 1) "name" 2) "xiaofang" 3) "age" 4) "26" 127.0.0.1:6382> hvals user2 1) "xiaofang" 2) "26" 127.0.0.1:6382> hkeys user2 1) "name" 2) "age" 127.0.0.1:6382> hincrby user age 2 (integer) 2 127.0.0.1:6382> hgetall user2 1) "name" 2) "xiaofang" 3) "age" 4) "26" 127.0.0.1:6382> hincrby user2 age 2 (integer) 28 127.0.0.1:6382> hgetall user2 1) "name" 2) "xiaofang" 3) "age" 4) "28" 127.0.0.1:6382> hincrbyfloat user2 age 2.0 "30" 127.0.0.1:6382> hincrbyfloat user2 age 2.5 "32.5" 127.0.0.1:6382> hgetall user2 1) "name" 2) "xiaofang" 3) "age" 4) "32.5"
list
列表結構
特點
有序
可以重複
左右兩邊插入彈出
API
練習
127.0.0.1:6382> rpush list1 a b c d (integer) 4 127.0.0.1:6382> lpush list1 e f g h i (integer) 9 127.0.0.1:6382> lrange list1 0 -1 1) "i" 2) "h" 3) "g" 4) "f" 5) "e" 6) "a" 7) "b" 8) "c" 9) "d" 127.0.0.1:6382> linsert list1 before i wu (integer) 10 127.0.0.1:6382> lrange list1 0 -1 1) "wu" 2) "i" 3) "h" 4) "g" 5) "f" 6) "e" 7) "a" 8) "b" 9) "c" 10) "d" 127.0.0.1:6382> linsert list1 after i jun (integer) 11 127.0.0.1:6382> lrange list1 0 -1 1) "wu" 2) "i" 3) "jun" 4) "h" 5) "g" 6) "f" 7) "e" 8) "a" 9) "b" 10) "c" 11) "d" 127.0.0.1:6382> lpop list1 "wu" 127.0.0.1:6382> rpop list1 "d" 127.0.0.1:6382> lrange list1 0 -1 1) "i" 2) "jun" 3) "h" 4) "g" 5) "f" 6) "e" 7) "a" 8) "b" 9) "c" 127.0.0.1:6382> lrem list1 1 i (integer) 1 127.0.0.1:6382> lrange list1 0 -1 1) "jun" 2) "h" 3) "g" 4) "f" 5) "e" 6) "a" 7) "b" 8) "c" 127.0.0.1:6382> rpush list1 c c c c c (integer) 13 127.0.0.1:6382> ltrem list1 -3 c (error) ERR unknown command 'ltrem' 127.0.0.1:6382> lrem list1 -3 c (integer) 3 127.0.0.1:6382> lrange list1 0 -1 1) "jun" 2) "h" 3) "g" 4) "f" 5) "e" 6) "a" 7) "b" 8) "c" 9) "c" 10) "c" 127.0.0.1:6382> lindex list 0 (nil) 127.0.0.1:6382> lindex list1 0 "jun" 127.0.0.1:6382> llen list1 (integer) 10 127.0.0.1:6382> lset list 0 wu (error) ERR no such key 127.0.0.1:6382> lset list1 0 wu OK 127.0.0.1:6382> lrange list1 0 -1 1) "wu" 2) "h" 3) "g" 4) "f" 5) "e" 6) "a" 7) "b" 8) "c" 9) "c" 10) "c"
應用
set
定義
Redis 的 Set 是 String 類型的無序集合。集合成員是唯一的,這就意味著集合中不能出現重複的數據。 Redis 中集合是通過哈希表實現的,所以添加,刪除,查找的複雜度都是 O(1)。
特點
無序
無重複
集合間操作
API
集合內的操作
命令 | 說明 | 時間複雜度 |
---|---|---|
sadd key element | 向集合key添加element(如果element已經存在,添加失敗) | O(1) |
srem key element | 將集合key中的element移除掉 | O(1) |
scard key | 計算集合大小 | O(1) |
sismember key element | 判斷element 是否在集合中 | O(1) |
srandmember key count | 從集合中隨機挑count個元素 | O(1) |
spop key | 從集合中隨機彈出一個元素 | O(1) |
smembers key | 獲取集合所有元素 | O(1) |
srem key element | 將集合key中的element移除掉 | O(1) |
集合間的操作
命令 | 說明 | 時間複雜度 |
---|---|---|
sdiff key1 key2 | 差集 | O(1) |
sinter key1 key2 | 交集 | O(1) |
sunion key1 key2 | 並集 | O(1) |
sidff/sinter/suion + store destkey | 將差集、交集、並集保存在destkey中 | O(1) |
注意
srandmember不會破壞集合
spop會破會
smembers 返回的是無序集合,並且要注意量很大的時候回阻塞
練習
127.0.0.1:6382> sadd set1 a b c d (integer) 4 127.0.0.1:6382> srem set1 a (integer) 1 127.0.0.1:6382> smembers set1 1) "d" 2) "c" 3) "b" 127.0.0.1:6382> scard set1 (integer) 3 127.0.0.1:6382> sismember set1 d (integer) 1 127.0.0.1:6382> srandmember set1 2 1) "d" 2) "b" 127.0.0.1:6382> srandmember set1 2 1) "b" 2) "c" 127.0.0.1:6382> spop set1 "c" 127.0.0.1:6382> smembers set1 1) "d" 2) "b" 127.0.0.1:6382> srem set1 d (integer) 1 127.0.0.1:6382> smembers set1 1) "b" 127.0.0.1:6382> sadd set1 1 2 3 4 5 (integer) 5 127.0.0.1:6382> sadd set2 a b c 12 8 9 1 2 (integer) 8 127.0.0.1:6382> sdiff set1 set2 1) "3" 2) "4" 3) "5" 127.0.0.1:6382> sinter set1 set2 1) "2" 2) "b" 3) "1" 127.0.0.1:6382> sunion set1 set2 1) "5" 2) "2" 3) "4" 4) "1" 5) "a" 6) "8" 7) "3" 8) "b" 9) "9" 10) "12" 11) "c" 127.0.0.1:6382>
實戰
抽獎系統, 用spop
贊過的文章,收藏過的文章等
標籤
共同關注
總結
zset
定義
Redis 有序集合和集合一樣也是string類型元素的集合,且不允許重複的成員。不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。有序集合的成員是唯一的,但分數(score)卻可以重複。
API
命令 | 說明 | 時間複雜度 |
---|---|---|
zadd key score element | 添加score和element | O(logN) |
zrem key element(可以是多個) | 將集合key中的element移除掉 | O(1) |
zscore key element | 返回元素的分數 | O(1) |
zincrby key increScore element | 增加或減少元素的分數 | O(1) |
zcard key | 返回元素的總個數 | O(1) |
zrank(zrevrank) key member | 返回元素的排名 | O(1) |
zrange(zrevrank) key start end [WITHSCORES] | 返回指定索引範圍內的升序元素[分值] | O(logN + m) |
zrangebyscore(zrevrangebyscore) key minScore maxScore | 返回指定分數範圍內的升序元素 | O(logN + m) |
zcount key minScore maxScore | 返回有序集合內在指定分數範圍內的個數 | O(logN + m) |
zremrangebyrank key start end | 刪除指定排名內的升序元素 | O(logN + m) |
zremrangebyscore key minScore maxScore | 刪除指定分數內的升序元素 | O(logN + m) |
ZINTERSTORE destination numkeys(表示key的個數) key [key ...] | 計算給定的一個或多個有序集的交集並將結果集存儲在新的有序集合 key 中 | |
ZUNIONSTORE destination numkeys key [key ...] | 計算給定的一個或多個有序集的並集,並存儲在新的 key 中 |
實戰
各種榜單(score:timestamp, saleCount, followCount)
redis客戶端的使用
下載
找相應語言的下載(一般選擇有笑臉和星星的)
https://redis.io/clients#php
redis的其他功能
慢查詢
生命週期
兩點說明
慢查詢發生在第3階段
客戶端超時不一定慢查詢,但慢查詢是客戶端超時的一個可能因素
兩個配置
slowlog-max-len
slowlog-log-slower-than
如何配置
慢查詢命令
slowlog get [n] : 獲取慢查詢隊列
slowlog len: 獲取慢查詢隊列長度
slowlog reset: 清空慢查詢隊列
運維經驗
pipeline:流水線
什麼是流水線
1次網絡命令通信模型
批量網絡命令通信模型
什麼是流水線
流水線的作用
兩點注意
redis的命令時間是微秒級別
pipeline每次條數要控制(網絡)
與原生操作對比
M操作
pipeline
使用建議
注意每次pipeline攜帶數據量
pipeline每次只能作用在一個redis節點上
M操作與pipeline區別
發佈訂閱
角色
發佈者
訂閱者
頻道
模型
API
publish channel message
subscribe [channel] 一個或者多個
unsubscribe [channel] 一個或者多個
練習
127.0.0.1:6382> publish weibomovie "hello world" (integer) 1 127.0.0.1:6382> publish weibomovie "hello world2" (integer) 1
另外一個cli
127.0.0.1:6382> SUBSCRIBE weibomovie Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "weibomovie" 3) (integer) 1 1) "message" 2) "weibomovie" 3) "hello world" 1) "message" 2) "weibomovie" 3) "hello world2"
發佈訂閱與消息隊列
Bitmap
位圖
API
命令 | 說明 | 時間複雜度 |
---|---|---|
setbit key offset value | 給位圖指定索引設置值 | O(1) |
getbit key offset | 獲取位圖指定索引的值 | O(1) |
bitcount key start end | 獲取位圖指定範圍(start 到end,單位為字節,如果不指定就獲取全部)位值為1的個數 | O(1) |
bitop op destkey key [key...] | 做多個bitmap的and,or,not,xor操作並將結果保存在destkey中 | O(1) |
bitpos key targetBit [start][end | 計算位圖指定範圍(start到end,單位為字節,如果不指定就是獲取全部)第一個偏移量對應的值等於targetBit的位置 | O(1) |
練習
127.0.0.1:6382> set hello big OK 127.0.0.1:6382> getbit hello (error) ERR wrong number of arguments for 'getbit' command 127.0.0.1:6382> getbit hello 0 (integer) 0 127.0.0.1:6382> setbit hello 0 1 (integer) 0 127.0.0.1:6382> get hello "\\xe2ig" 127.0.0.1:6382> set hell a OK 127.0.0.1:6382> bitcount hell (integer) 3 127.0.0.1:6382> bitop and hell hello (integer) 3 127.0.0.1:6382> set a a OK 127.0.0.1:6382> set b b OK 127.0.0.1:6382> bitop and c a b (integer) 1 127.0.0.1:6382> get c "`" 127.0.0.1:6382> bitpos a 1 (integer) 1 127.0.0.1:6382> bitpos a 0 (integer) 0 127.0.0.1:6382> set user2 100 OK
獨立用戶統計
重要理解 使用位圖去記錄用戶uid,其實就是記錄索引值,比如userid=100代表位圖下標100的值為1
使用經驗
type=string,最大512MB
注意setbit時的偏移量,可能有較大耗時
位圖不是絕對好
HyperLogLog
新的數據結構
API
命令 | 說明 |
---|---|
pfaddd key element [element...] | 向hyperloglog添加元素 |
pfcount key [key...] | 計算hyperloglog的獨立總數 |
pfmerge destkey sourceKey [sourcekey...] | 合併多個hyperloglog |
練習
127.0.0.1:6382> pfadd puser1 "u1" "u2" "u3" (integer) 1 127.0.0.1:6382> pfcount puser1 (integer) 3 127.0.0.1:6382> pfadd puser2 "u3" "u4" "u5" (integer) 1 127.0.0.1:6382> pfmerge puser puser1 puser2 OK 127.0.0.1:6382> pfcount puser (integer) 5
內存消耗
使用經驗
是否能容忍錯誤(錯誤率:0.81%)
是否需要單條數據(沒有辦法取出)
GEO
GEO是什麼
5個城市經緯度
API
命令 | 說明 |
---|---|
geoadd key longitude latitude member [longitude latitude member ...] | 增加地理位置信息 |
geopos key member[member... | 獲取地理位置信息 |
geodist key member1 member2[unit] | 獲取兩個地理位置的距離,unit:m,km,mi,ft |
georadius | 獲取指定位置範圍內的地理位置信息集合 |
練習
127.0.0.1:6382> geoadd beijing 116.28 39.55 (error) ERR wrong number of arguments for 'geoadd' command 127.0.0.1:6382> geoadd geo 116.28 39.55 beijing 117.12 39.08 tianjin (integer) 2 127.0.0.1:6382> geopos geo beijing 1) 1) "116.28000229597091675" 2) "39.5500007245470826" 127.0.0.1:6382> geodist geo beijing tianjin "89206.0576" 127.0.0.1:6382>
相關說明
since 3.2+
type geoKey = zset
沒有刪除API:zrem key member
redis持久化的取捨和選擇
持久化的作用
什麼是持久化
redis所有數據保存在內存中, 對數據的更新將異步地保存到磁盤上
持久化的實現方式
快照
-
mysql dump
redis RDB
寫日誌
mysql binlog
hbase hLog
redis AOF
RDB
什麼是RDB
觸發機制-主要三種方式
save(同步)
* 文件策略:如存在老的RDB文件,新替換老 * 複雜度:O(N)
bgsave(異步)
自動配置
**相關配置
配置參數 | 值 |
---|---|
save | 900 1 |
save | 300 10 |
save | 60 10000 |
dbfilename | dump-${port}.rdb |
dir | /bigdishpath |
stop-writes-on-bgsav-error | yes |
rdbcompression | yes |
save與bgsave
觸發機制-不容忽略的方式
其他的方式也會觸發生成RDB文件
全量複製
-
debug reload
shutdown
總結
RDB是Redis內存到硬盤的快照,用於持久化
save通常會阻塞Redis
bgsave不會阻塞redis,但是會fork新進程
save自動配置滿足任一就會被執行
有些觸發機制不容忽視
AOF
RDB現存問題
耗時,好性能
不可控,丟失數據
什麼是AOF
創建
恢復
AOF三種策略
always
everysec
no
三種策略比較
AOF重寫
AOF重寫的作用
減少硬盤佔用量
加速恢復速度
AOF重寫實現的兩種方式
bgrewriteaof
aof重寫配置
AOF重寫流程
配置
RDB與AOF的選擇
RDB最佳策略
關
集中管理
主從,從開
AOF最佳策略
開,緩存和存儲
AOF重寫集中管理
everysec
閱讀更多 JAVA技術開發 的文章