單線程的redis如何處理阻塞命令

今天有個問題,既然redis是單線程的,那麼像BLPOP這種的阻塞命令不會一直佔用着線程,其他命令無法執行嗎?然而事實上是可以執行的。

這個文章通過redis的源碼講的很清楚了。我總結補充一下人家的東西。
https://www.jianshu.com/p/xsMzfn

BLPOP key1 [key2 ] timeout 移出並獲取列表的第一個元素,
如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素爲止

redis的線程模型,是接收客戶端命令的線程時 I/O 多路複用的,再通過文件事件分配器單線程執行的。如下圖,程序總是會將所有產生事件的套接字都入隊到一個隊列裏面, 然後通過這個隊列, 以有序(sequentially)、同步(synchronously)、每次一個套接字的方式向文件事件分派器傳送套接字: 當上一個套接字產生的事件被處理完畢之後(該套接字爲事件所關聯的事件處理器執行完畢), I/O 多路複用程序纔會繼續向文件事件分派器傳送下一個套接字
在這裏插入圖片描述

那實際上我們關心的BLPOP 命令的執行就是在文件事件分派器分派後是怎麼執行的了。

對BLPOP命令的處理流程是這樣的:

  1. redis先找到對應的key的list,如果list不爲空則pop一個數據返回給客戶端;
  2. 如果list爲空,或者list不存在,就將該key添加到一個blockling_keys的字典中,value就是想訂閱該key的client鏈表。此時對應的client的爲block狀態
  3. 當有PUSH 類型的命令進來的時候,先從blocking_keys中查找是否存在對應的key,如果存在就往ready_keys這個鏈表中添加該key;同時將value插入到對應的list中,並響應客戶端。
  4. 每次處理完客戶端命令後都會遍歷ready_keys,並通過blocking_keys找到對應的client,依次將對應list的數據pop出來並響應對應的client;同時檢查是否需要再次block。

整個阻塞執行過程相當於是分散開的,每次請求結束後都判斷之前的阻塞列表是否滿足執行條件,類似我們用輪詢來實現長連接的功能。所以看似阻塞的命令對其他命令的執行時不會有影響的,它們依然是單線程的。

參考:https://www.cnblogs.com/barrywxx/p/8570821.html
https://www.jianshu.com/p/xsMzfn

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章