天天看點

Redis變慢了,到底慢在哪兒?(1)

00、Redis變慢了,到底慢在哪兒?

最近由于工作需要,在維護線上的Redis,Redis相關的原理部分看的比較多,Redis最常見的業務問題就是響應慢,今天我們來看看Redis慢在哪裡?以及如何解決這些慢的現象。

首先來看有可能引起Redis變慢的那些情況。其實,Redis變慢的主要因素是各種類型的阻塞,可以這麼說:阻塞是Redis的噩夢。Redis是單線程處理模型,一旦某個環節出現阻塞,後續環節肯定會受到影響,這是毋庸置疑的。

總體上來說,Redis的阻塞存在很多可能,今天重點說以下2個方面:

1、Redis内部的阻塞式操作或者指令

2、CPU核心以及NUMA架構

01、Redis内部的阻塞式操作或指令

假設你的Redis是以最複雜的叢集的模式部署的,那麼在Redis用戶端和Redis服務互動的時候,整個鍊路包含網絡IO、磁盤寫入、主從節點複制、切片叢集資料遷移等等,這些步驟都可能産生阻塞,下面逐一分析。

1、阻塞式指令會影響Redis的性能。

集合的全量查詢keys *等指令、當集合中有N個資料的時候,複雜度就是O(n),阻塞的時間和資料個數正相關;

删除指令也會影響Redis的性能,删除key的時候,作業系統會将釋放的記憶體塊插入一個空閑的記憶體塊連結清單,這個操作本身會阻塞目前的應用,如果釋放的key占用記憶體較多,例如是一個bigKey,那麼大機率會影響Redis的性能

清空資料庫的指令flushall和flushdb也存在類似的阻塞風險

2、AOF落盤時候産生阻塞

Redis中記錄AOF日志時候,會根據不同的回寫政策來進行資料落盤,跟磁盤的互動總是很慢的,如果大量的寫操作需要同步落盤,就會阻塞主線程了。

3、主從節點互動産生的阻塞

主從節點進行互動的時候,從節點上有2個阻塞點,第一是從節點需要使用flushdb清空資料庫,如果從節點之前有資料,這可能造成阻塞;另外一個就是從節點需要加載主節點發送過來的RDB檔案,如果RDB檔案很大,則會加載很慢,産生阻塞

4、切片叢集Redis Cluster互動時候的阻塞點

切片叢集在進行bigkey遷移的時候,會造成主線程的阻塞,因為Redis Cluster采用了同步遷移。

02、CPU核心NUMA架構的影響

多核CPU下面,對Redis的性能影響還是挺大的。我們先來看看多核心CPU的一般架構。

在目前主流伺服器上,一般都擁有多個CPU處理器,而一個CPU處理器,會擁有10~20個實體核心。如果一個伺服器擁有多個CPU處理器,那麼我們也成這個伺服器擁有多個CPU Socket,Socket簡單了解,就是一個CPU處理器,

Redis變慢了,到底慢在哪兒?(1)

如圖為4核心CPU的架構,其中,CPU核心1、2在同一個Socket中,CPU核心3、4在另外一個Socket中。Socket之間,通過CPU總線來連接配接,每個Socket控制一塊記憶體。

1、跨Socket的通路

如果一個Redis服務部署在這樣的伺服器上,它有可能在Socket1和Socket2之間來回切換,假設一個Redis應用現在Socket1上運作了一段時間,那麼它的資料會儲存在Socket1所對應的記憶體上,如果它再次被排程到另外一個Socket2上,此時,應用再進行記憶體通路的時候,就需要通過總線跨越到Socket1上來通路記憶體,這種通路屬于遠端通路,它會增加通路的延遲。

Redis變慢了,到底慢在哪兒?(1)

而我們常說的NUMA,則是對上述情況的一種描述,叫非統一記憶體通路架構(Non-uniform Memory Access,簡稱NUMA架構)

2、頻繁的CPU核心切換

除了跨Socket通路外,在多核心通路的場景下,如果一個程式需要在一個新的CPU核心上運作,那麼運作時資訊就要重新加載到新的CPU核心上,新的CPU核心也需要更新緩存中的資訊,這也會間接導緻運作時間增加。如果這個核心之間的排程很頻繁,則會大大影響Redis的性能。