Redis開發與運維學習筆記—(2)

  • 2020 年 3 月 31 日
  • 筆記

Redis的單線程架構

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命令將慢查詢日誌持久化到其他存儲中,然後定製可視化界面進行查詢。