9個提升逼格的Redis命令
來自:阿飛Javaer(微信號:AfeiJavaer)
keys
我把這個命令放在第一位,是因為筆者曾經做過的項目,以及一些朋友的項目,都因為使用keys
這個命令,導致出現性能毛刺。這個命令的時間複雜度是O(N),而且redis又是單線程執行,在執行keys時即使是時間複雜度只有O(1)例如SET或者GET這種簡單命令也會堵塞,從而導致這個時間點性能抖動,甚至可能出現timeout。
強烈建議生產環境屏蔽keys命令
(後面會介紹如何屏蔽)。
scan
既然keys命令不允許使用,那麼有什麼代替方案呢?有!那就是scan
命令。如果把keys命令比作類似select * from users where username like "%afei%"
這種SQL,那麼scan應該是select * from users where id>? limit 10
這種命令。
官方文檔用法如下:
SCAN cursor [MATCH pattern] [COUNT count]
初始執行scan命令例如scan 0
。SCAN命令是一個基於游標的迭代器。這意味著命令每次被調用都需要使用上一次這個調用返回的游標作為該次調用的游標參數,以此來延續之前的迭代過程。當SCAN命令的游標參數被設置為0時,伺服器將開始一次新的迭代,而
當redis伺服器向用戶返回值為0的游標時,表示迭代已結束
,這是唯一迭代結束的判定方式,而不能通過返回結果集是否為空判斷迭代結束。使用方式:
127.0.0.1:6380> 0 1 "22" 2 1 "23" 2 "20" 3
)
"14"
4
)"2"
5
)"19"
6
)"9"
7
)"3"
8
)
"21"
9
)"12"
10
)"25"
11
)"7"
返回結果分為兩個部分:第一部分即1)就是下一次迭代游標,第二部分即2)就是本次迭代結果集。
slowlog
上面提到不能使用keys命令,如果就有開發這麼做了呢,我們如何得知?與其他任意存儲系統例如mysql,mongodb可以查看慢日誌一樣,redis也可以,即通過命令slowlog
。用法如下:
SLOWLOG [argument]
subcommand主要有:
get
,用法:slowlog get [argument],獲取argument參數指定數量的慢日誌。len
,用法:slowlog len,總慢日誌數量。reset
,用法:slowlog reset,清空慢日誌。
執行結果如下:
127.0 .0 .1 6380 get 5 1 1 integer 2
2
) (integer
)1532656201
3
) (integer
)2033
4
)1
)"flushddbb"
2
)
1
) (integer
)1
---- 慢日誌編碼,一般不用care2
) (integer
)1532646897
---- 導致慢日誌的命令執行的時間點,如果api有timeout,可以通過對比這個時間,判斷可能是慢日誌命令執行導致的3
) (integer
)26424
---- 導致慢日誌執行的redis命令,通過4
)可知,執行config rewrite導致慢日誌,總耗時
26
ms+4
)1
)"config"
2
)"rewrite"
命令耗時超過多少才會保存到slowlog中,可以通過命令
config set slowlog-log-slower-than 2000
配置並且不需要重啟redis。注意:單位是微妙,2000微妙即2毫秒。
rename-command
為了防止把問題帶到生產環境,我們可以通過配置文件重命名一些危險命令,例如keys
等一些高危命令。操作非常簡單,只需要在conf配置文件增加如下所示配置即可:
rename rename rename keys
bigkeys
隨著項目越做越大,緩存使用越來越不規範。我們如何檢查生產環境上一些有問題的數據。bigkeys
就派上用場了,用法如下:
--bigkeysredis-cli -p 6380
執行結果如下:
526 in key in is 1524 2.90 string "test" has 10005 bytes "commentlist" has 13 items 524 with 15181 99.62 of 28.97 2 with 19 00.38 of 9.50 0 with 0 00.00 of 0.00 0 with 0 00.00 of 0.00 0 with 0 00.00 of 0.00... ...-------- summary -------Sampled
最後5行可知,沒有set,hash,zset幾種數據結構的數據。string類型有524個,list類型有兩個;通過Biggest ... ...
可知,最大string結構的key是test
,最大list結構的key是commentlist
。
需要注意的是,這個
bigkeys得到的最大,不一定是最大
。說明原因前,首先說明bigkeys
的原理,非常簡單,通過scan命令遍歷,各種不同數據結構的key,分別通過不同的命令得到最大的key:
如果是string結構,通過
strlen
判斷;如果是list結構,通過
llen
判斷;如果是hash結構,通過
hlen
判斷;如果是set結構,通過
scard
判斷;如果是sorted set結構,通過
zcard
判斷。
正因為這樣的判斷方式,雖然string結構肯定可以正確的篩選出最佔用緩存,也可以說最大的key。但是list不一定,例如,現在有兩個list類型的key,分別是:numberlist--[0,1,2],stringlist--["123456789123456789"],由於通過llen判斷,所以numberlist要大於stringlist。而事實上stringlist更佔用內存。其他三種數據結構hash,set,sorted set都會存在這個問題。使用bigkeys一定要注意這一點。
monitor
假設生產環境沒有屏蔽keys等一些高危命令,並且slowlog中還不斷有新的keys導致慢日誌。那我們如何揪出這些命令是由誰執行的呢?這就是monitor
的用處,用法如下:
redis-cli -p 6380 monitor
如果當前redis環境OPS比較高,那麼建議結合linux管道命令優化,只輸出keys命令的執行情況:
# redis-cli -p 6380 monitor | grep keys 1532645266.656525 0 10.0 .0 .1 43544 "keyss" "*" 1532645287.257657 0 10.0 .0 .1 43544 "keyss" "44*"[afei@redis ~]
執行結果中很清楚的看到keys命名執行來源。通過輸出的IP和埠信息,就能在目標伺服器上找到執行這條命令的進程,揪出元兇,勒令整改。
info
如果說哪個命令能最全面反映當前redis運行情況,那麼非info莫屬。用法如下:
INFO [section]
section可選值有:
Server
:運行的redis實例一些信息,包括:redis版本,操作系統信息,埠,GCC版本,配置文件路徑等;Clients
:redis客戶端信息,包括:已連接客戶端數量,阻塞客戶端數量等;Memory
:使用內存,峰值內存,內存碎片率,內存分配方式。這幾個參數都非常重要;Persistence
:AOF和RDB持久化信息;Stats
:一些統計信息,最重要三個參數:OPS(instantaneous_ops_per_sec
),keyspace_hits
和keyspace_misses
兩個參數反應緩存命中率;Replication
:redis集群信息;CPU
:CPU相關信息;Keyspace
:redis中各個DB里key的信息;
config
config是一個非常有價值的命令,主要體現在對redis的運維。因為生產環境一般是不允許隨意重啟的,不能因為需要調優一些參數就修改conf配置文件並重啟。redis作者早就想到了這一點,通過config命令能熱修改一些配置,不需要重啟redis實例,可以通過如下命令查看哪些參數可以熱修改:
getconfig
熱修改就比較容易了,執行如下命令即可:
setconfig
例如:config set slowlog-max-len 100
,config set maxclients 1024
這樣修改的話,如果以後由於某些原因redis實例故障需要重啟,那通過config熱修改的參數就會被配置文件中的參數覆蓋,所以我們需要通過一個命令將config熱修改的參數刷到redis配置文件中持久化,通過執行如下命令即可:
config
執行該命令後,我們能在config文件中看到類似這種信息:
# 如果conf中本來就有這個參數,通過執行config set
#
如果conf中沒有這個參數,通過執行config
set
,那麼redis會追加在Generated by CONFIG REWRITE字樣後面#
Generated by CONFIG REWRITE
save 600 60slowlog-max-len 100set
set命令也能提升逼格?是的,我本不打算寫這個命令,但是我見過太多人沒有完全掌握這個命令,官方文檔介紹的用法如下:
SET key value [EX seconds] [PX milliseconds] [NX|XX]
你可能用的比較多的就是set key value
,或者SETEX key seconds value
,所以很多同學用redis實現分散式鎖分為兩步:首先執行SETNX key value
,然後執行EXPIRE key seconds
。很明顯,這種實現有很嚴重的問題,因為兩步執行不具備原子性,如果執行第一個命令後出現某些未知異常導致無法執行EXPIRE key seconds
,那麼分散式鎖就會一直無法得到釋放。
通過SET
命令實現分散式鎖的正式姿勢應該是SET key value EX seconds NX
(EX和PX任選,取決於對過期時間精度要求)。另外,value也有要求,最好是一個類似UUID這種具備唯一性的字元串。當然如果問你redis是否還有其他實現分散式鎖的方案。你能說出redlock,那對方一定眼前一亮,心裡對你豎起大拇指,但嘴上不會說。
關於redis分散式鎖方案,強烈建議你閱讀redis官方文檔Redis分散式鎖:http://redis.cn/topics/distlock.html
●編號384,輸入編號直達本文
●輸入m獲取文章
目錄
推薦↓↓↓
Web開發
更多推薦
《
18個技術類公眾微信
》
涵蓋:程序人生、演算法與數據結構、黑客技術與網路安全、大數據技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。
推薦閱讀:
※作為一名舞蹈教師應該如何提升自我?
※前廳和後廚要善於換位思考,才能提升餐廳業績
※身邊有這樣的人,能提升自己的福氣!你身邊有嗎?
※畫質提升明顯 佳能70-200mm f/4二代評測
※《全民解答》第19集:如何提升反手拉球上台率 乒乓球教學視頻