Redis開發與運維學習筆記—(2)
- 2020 年 3 月 31 日
- 筆記
Redis使用了單線程架構和I/O多路復用模型來實現高性能的內存數據庫服務,我們來看Redis的單線程命令處理機制。
我們同時打開三個窗口,第1個窗口輸入:
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> get hello
"world"
第2窗口輸入:
127.0.0.1:6379> incr counter
(integer) 1
第3個窗口輸入:
127.0.0.1:6379> incr counter
(integer) 2
因為在redis中是單線程來處理命令的,所以一條命令從客戶端到達服務器端之前不會被立即執行,而是會進入一個隊列中,上面3個命令之間的執行順序是不確定的,但是可以確定的是,肯定不會有兩條命令被同時執行。
為什麼單線程的redis還能處理得那麼快?
主要原因如下:
1、redis是純內存訪問,它將所有的數據存放在內存中,內存的相應時間大約為100ns,這是redis達到每秒萬級別訪問的基礎。
2、非阻塞I/O,redis使用epoll作為I/O多路復用技術的實現,再加上Redis自身的時間處理模型將epoll中的連接、讀寫、關閉都轉換為時間,不在網絡I/O上浪費過多的時間。
3、單線程,避免了線程切換和資源競爭。這樣服務端也就沒有了鎖爭用
慢查詢分析
要了解redis的慢查詢,首先需要知道redis的查詢模型:

redis的查詢模型分為4步:
1、發送命令
2、排隊
3、執行命令
4、返回結果
redis的慢查詢只統計步驟3的時間。
慢查詢的2個配置參數
對於慢查詢,redis配置了2個關鍵參數,其中第一個是慢查詢的閾值:slowlog-log-slower-than和slowlog-max-len配置來解決這兩個問題。其中:
第一個參數單位是微妙(1s=1000ms=1000000ns),默認值是1000,加入某個命令執行時間超過這個值,那麼他就會被記錄在慢查詢日誌中。
這裡還有一點需要注意:如果設置slowlog的參數值為0,則會記錄所有的命令,如果slowlog值小於0,則對於任何命令都不會記錄。
slowlog-max-len指的是慢查詢日誌列表的最大長度,如果這個值設置為5,則當慢查詢到達6的時候,最早的一個命令將被移除列表。
在redis中,有2種修改參數的方法,第一種是修改配置文件,另一種是使用config set命令動態修改,如果要將redis的配置持久化到本地的配置文件,則需要執行config rewrite的命令。我們看看參數的默認值:
[root@VM_48_10_centos redis]# cat redis.conf |grep slowlog slowlog-log-slower-than 10000 slowlog-max-len 128
當我們使用config rewrite之後,可以看到:
[root@VM_48_10_centos redis]# redis-cli 127.0.0.1:6379> config set slowlog-max-len 256 OK 127.0.0.1:6379> config rewrite 20673:M 26 Mar 23:14:58.643 # CONFIG REWRITE executed with success. OK 127.0.0.1:6379> exit [root@VM_48_10_centos redis]# cat redis.conf |grep slowlog slowlog-log-slower-than 10000 slowlog-max-len 256
已經成功的將配置寫入了配置文件中了。
慢查詢如何查看?
redis的慢查詢是存放在redis的內存列表中的,但是redis並沒有暴露這個列表的鍵,而是通過一組命令來實現對慢查詢日誌的訪問和管理:
slowlog get [n]
上面的命令可以返回當前redis的慢查詢,參數n可以指定條數。下面是測試例子:
[root@VM_48_10_centos redis]# redis-cli 127.0.0.1:6379> config set slowlog-log-slower-than 0 OK 127.0.0.1:6379> set hello world OK 127.0.0.1:6379> get hello "world" 127.0.0.1:6379> slowlog get 2 1) 1) (integer) 4 2) (integer) 1585235910 3) (integer) 10 4) 1) "slowlog" 2) "get" 3) "1" 2) 1) (integer) 3 2) (integer) 1585235905 3) (integer) 4 4) 1) "get" 2) "hello"
每條日誌有4個屬性,分別是redis慢日誌的標識id、發生的時間戳、命令耗時和參數。
還有:
slowlog len命令用來查詢慢查詢當前的條數。
slowlog reset用來重置慢查詢列表
127.0.0.1:6379> slowlog len (integer) 6 127.0.0.1:6379> slowlog reset OK 127.0.0.1:6379> slowlog len (integer) 1
我們由於配置了slowlog-log-slow..為0,所以清理之後,還會記錄slowlog len本身。
幾點注意:
1、線上的話,slowlog-max-len建議調大,因為記錄慢查詢時redis會對長命令做截斷處理,所以並不會佔用大量內存。線上的可以設置1000以上。
2、slowlog-log-slower-than默認值超過10ms就判定為慢查詢,需要根據redis的並發量調整,如果某個應用是高並發的,如果命令執行時間在1ms以上,則OPS將不到1000,要根據實際情況來調整這個參數。
3、慢查詢只記錄命令的執行時間,並不包括命令排隊和網絡傳輸時間,因此客戶端執行命令的時間會大於命令實際執行時間,因此當線上出現阻塞時,應當先分析慢查詢,從而排除慢查詢造成的阻塞。
4、因為慢查詢日誌是一個先進先出的隊列,在慢查詢比較多的情況下,可以定期執行slow get命令將慢查詢日誌持久化到其他存儲中,然後定製可視化界面進行查詢。