keys
dbsize #計算key的總數
exists key #檢查key是否存在
del key [key] #刪除指定key-value
type key #返回key的類型
expire key seconds #key在seconds過時
ttl key #查看key剩餘的過時時間
persist key #去掉key的過時時間
複製代碼
-2表示過時
-1表明key存在,而且沒有過時時間
kyes基本不在生產環境使用html
keys * #遍歷全部key
key [pattern]
複製代碼
命令 | 時間複雜度 |
---|---|
keys | O(n) |
dbsize | O(1) |
del | O(1) |
exists | O(1) |
expire | O(1) |
type | O(1) |
單線程須要注意什麼?java
keys, flushall, flushdb, slow lua script, mutil/exec, operate big value(collention)
fysnc file descriptor
close file descriptor
複製代碼
get key #獲取key對應的value O(1)
set key value #設置key-value O(1)
del key #刪除key-value O(1)
mset key value key value #批量設置key-value O(n)
mget key key #批量獲取key-value O(n)
incr key #key自增1,若是key不存在,自增後get(key)=1 O(1)
decr key #key自減1,若是key不存在,自減後get(key)=-1 O(1)
incrby key k #key自增k,若是key不存在,自增後get(key)=k O(1)
decrby key k #key自減k,若是key不存在,自減後get(key)=-k O(1)
set key value #無論key是否存在,都設置 O(1)
setnx key value #key不存在,才設置 O(1)
set key value xx #key存在,才設置 O(1)
getset key newvalue #set key newvalue並返回舊的value
append key value #將value追加到舊的value
strlen key #返回字符串的長度(注意中文)
incrbyfloat key 3.5 #增長key對應的值3.5
getrange key start end #獲取字符串指定下標的全部的值
setrange key index value #設置下標全部對應的值
複製代碼
哈希鍵值結構mysql
hmset key field value field value #批量設置 O(n)
hmget key field field #批量獲取 O(n)
hget key field #獲取hash key對應的field的value O(1)
hset key field value #設置hash key對應field的value O(1)
hdel key field #刪除hash key對應的field的value O(1)
hexists key field #判斷hash key 是否有field O(1)
hlen key #獲取hash key field的數量 O(1)
hgetall key #h返回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 #設置hash key對應field的value(如field存在,則失敗) O(1)
hincrby key field intCounter #hash key 對應的field的value自增intCounter O(1)
hincrbyfloat key field floatCounter #hincrby浮點數版 O(1)
複製代碼
記錄網站每一個用戶我的主頁的訪問量linux
#redis實現
incr userid:pagevies(單線程,無競爭)
hincrby user:1:info pageview count
#java模擬代碼
public VideoInfo get(long id){
String redisKey = redisPrefix + id;
Map<String,String> hashMap = redis.hgetAll(redisKey);
VideoInfo videoInfo = transferMapToVideo(hashMap);
if(videoInfo == null){
videoInfo = mysql.get(id);
if(videoInfo != null){
redis.hmset(redisKey, transferMapToVideo(videoInfo))
}
}
return videoInfo;
}
複製代碼
當心使用hgetall(redis單線程) 例子:如保存一個用戶的信息的實現,下面說3種情形,固然還有更多種其餘方式ios
命令 | 優勢 | 缺點 |
---|---|---|
string v1 | 編程簡單,可能節約內存 | 1. 序列號開銷 2. 設置屬性要操做整個數據 |
string v2 | 直觀,能夠部分更新 | 1. 內存佔用較大 2. key較爲分散 |
hash | 直觀、節省空間、能夠部分更新 | 1. 編程稍微複雜 2. ttl很差控制 |
特色:有序、能夠重複、左右兩邊插入彈出git
rpush key value value ...valueN #從列表右端插入值(1-N個)
lpush key value value ...valueN #從列表左端插入值(1-N個)
linsert key before|after value newValue #在list指定的前|後插入newValue
lpop key #從列表左側彈出一個item
rpop key #從列表右側彈出一個item
#根據count值,從列表中刪除全部value相等的項
#count > 0,從左到右,刪除最多count個value相等的項
#count < 0,從右到左,刪除最多Math.abs(count)個value相等的項
#count = 0,刪除全部value相等的項
lrem key count value
ltrim key start end #按照索引範圍修剪列表 O(n)
lrange key start end #獲取列表指定索引範圍全部item O(n)
llen key #獲取列表長度 O(1)
lset key index newValue #設置列表指定索引值爲newValue O(n)
blpop key timeout #lpop阻塞版本,timeout是阻塞超時時間,timeout=0爲永遠不阻塞 O(1)
brpop key timeout #rpop阻塞版本,timeout是阻塞超時時間,timeout=0爲永遠不阻塞 O(1)
##小建議-數據結構類比
lpush + lpop = stack
lpush + rpop = queue
lpush + ltrim = capped collection
lpush + brpop = message quere
複製代碼
慢查詢命令redis
slowlog get [n] #獲取慢查詢隊列
slowlog len #獲取慢查詢隊列長度
slowlog reset #清空慢查詢隊列
複製代碼
1. 默認值
config get slowlog-max-len = 128
config get slowlog-log-slower-than = 1000
2. 修改配置文件重啓
3. 動態配置
config set slowlog-max-len 1000
config set slowlog-log-slower-than 1000
複製代碼
運維經驗sql
批量網絡命令通訊模型 編程
什麼是流水線 流水線做用命令 | N個命令操做 | 1次pipeline(n個命令) |
---|---|---|
時間 | n次網絡 + n次命令 | 1次網絡 + n次命令 |
數據量 | 1條命令 | n條命令 |
pipeline-Jedis實現緩存
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<type>jar</type>
</dependency>
#沒用pipeline, 1W次hset須要50s
Jedis jedis = new Jedis("127.0.0.1", 6379);
for(int i=0;i<10000;i++){
jedis.hset("hashkey:"+i,"field"+i, "value"+i);
}
#使用pipeline
Jedis jedis = new Jedis("127.0.0.1", 6379);
for(int i=0;i<100;i++){
Pipeline pipeline = jedis.pipelined();
for(int j=i*100; j<(i+1)*100;j++){
pipeline.hset("hashkey:"+j,"field"+j, "value"+j);
}
pipeline.syncAndReturnAll();
}
複製代碼
使用建議
角色 發佈者(publisher) 訂閱者(subscriber) 頻道(channel) 模型
publish channel message #發佈消息
subscribe [channel] #一個或多個
unsubscribe [channel] #一個或多個
psubscribe [pattern...] #訂閱模式
punsubscribe [pattern...] #退訂指定的模式
pubsub channels #列出至少有一個訂閱者的頻道
pubsub numsub [channel...] #列出給定頻道的訂閱者數量
pubsub numpat #列出被訂閱模式的數量
複製代碼
setbit key offset value #給位圖指定索引設置值
getbit key offset #獲取位圖指定索引的值
bitcount key [start end] #獲取位圖指定範圍(start到end,單位爲字節,若是不指定就是獲取所有)位值爲1的個數
bitop key targetBit [start] [end] #計算位圖指定範圍第一個偏移量對應的值等於targetBit的位置
複製代碼
獨立用戶統計
數據類型 | 每一個userid佔用空間 | 須要存儲的用戶量 | 所有存儲量 |
---|---|---|---|
set | 32位(假設userid用的是整型,實際場景不少用長整型) | 50000000 | 32位*50000000=190.7348633MB |
Bitmap | 1位 | 100000000 | 1位*100000000=11.920929MB |
一天 | 一個月 | 一年 | ||
---|---|---|---|---|
set | 200M | 6G | 72G | 大約值 |
Bitmap | 12.5M | 375M | 4.5G | 大約值 |
只有十萬獨立用戶呢?
數據類型 | 每一個userid佔用空間 | 須要存儲的用戶量 | 所有存儲量 |
---|---|---|---|
set | 32位(假設userid用的是整型,實際場景不少用長整型) | 100000 | 32位*1000000=0.3814697MB |
Bitmap | 1位 | 100000 | 1位*100000000=0.0119209MB |
使用建議
pfadd key element [element...] #向hyperloglog添加元素
pfcount key [key] #計算hyperloglog的獨立總數
pfmerge destkey sourcekey [sourcekey] #合併多個hyperloglog
複製代碼
type geoKey = zset
zrem key member
geo key longitude latitude member [longitude latitude member...] #增長地理位置信息
geopos key member [member...] #獲取地理位置信息
geodist key member1 member2 [unit] #獲取兩個地理位置的距離,unit:m、km、mi、ft
複製代碼
bgsave
save與bgsave
命令 | save | bgsave |
---|---|---|
IO類型 | 同步 | 異步 |
阻塞 | 是 | 是(阻塞發生再fork) |
複雜度 | O(n) | O(n) |
優勢 | 不會消耗額外內存 | 不阻塞客戶端命令 |
缺點 | 阻塞客戶端命令 | 須要fork,消耗內存 |
# 配置redis.conf
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
dir ./
stop-write-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
#最佳配置
dbfilename dump-${port}.rdb #指定對應哪一個redis的備份
dir /bigdiskpath #指定具體文件目錄
stop-write-on-bgsave-error yes
rdbcompression yes
複製代碼
觸發機制
RDB總結
RDB有什麼問題 耗時、耗性能 不可控、丟失數據
AOF運行原理-建立
AOF運行原理-恢復AOF的三種策略 always
everysec no命令 | always | everysec | no |
---|---|---|---|
優勢 | 不丟失數據 | 每秒一次fsync丟一秒數據 | 不用管 |
缺點 | IO開銷較大,通常的sata盤只有幾百TPS | 丟一秒數據 | 不可控 |
AOF重寫
AOF重寫2種方式
bgrewriteaof命令
自動
配置名 | 含義 |
---|---|
auto-aof-rewrite-min-size | AOF文件重寫須要的尺寸 |
auto-aof-rewrite-percentage | AOF文件增加率 |
統計名 | 含義 |
---|---|
aof_current_size | AOF當前尺寸(單位:字節) |
aof_base_size | AOF上次啓動和重寫的尺寸(單位:字節) |
自動觸發實際(同時知足)
#配置redis.conf
appendonly yes
appendfilename "appendonly-${port}.aof"
appendfsync everysec
dir /bigdiskpath
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
複製代碼
AOF重寫流程
AOF阻塞問題
大於2秒會形成主線程阻塞,沒法進行後續客戶端發來的命令 每秒刷盤的策略不止是隻丟失1秒的數據,也有多是幾秒如何定位
info Persistence
(沒法看到具體時間點)RDB和AOF選擇
命令 | RDB | AOF |
---|---|---|
啓動優先級 | 低 | 高 |
體積 | 小 | 大 |
恢復速度 | 快 | 慢 |
數據安全性 | 丟數據 | 根據策略決定 |
輕重 | 重 | 輕 |
最佳策略
改善fork
子進程開銷與優化
單機有什麼問題? 機器故障 容量瓶頸 QPS瓶頸
簡單總結slaveof ip port
slave-read-only yes
slaveof on one
複製代碼
全量複製
開銷:部分複製
Redis主從複製和集羣配置
主從複製的常見問題 讀寫分離配置不一致
規避全量複製
規避複製風暴
主從複製-master宕掉故障處理
Redis 數據結構與內存管理策略(上)
Redis 數據結構與內存管理策略(下)
原理、方法左右開弓,大神帶你細解Redis內存管理和優化
redis調整內核參數
Redis安全
redis 熱點Key的發現與解決之道
redis4.0之基於LFU的熱點key發現機制