主頁 >  其他 > Redis多執行緒原理詳解

Redis多執行緒原理詳解

2020-11-25 19:35:11 其他

本篇文章為你解答以下問題:
  • 0:redis單執行緒的實作流程是怎樣的?
  • 1:redis哪些地方用到了多執行緒,哪些地方是單執行緒?
  • 2:redis多執行緒是怎么實作的?
  • 3:redis多執行緒是怎么做到無鎖的?
  0:redis單執行緒的實作流程是怎樣的? Redis一開始是單執行緒模型,在一個執行緒中要同時處理兩種事件:檔案事件和時間事件 檔案事件主要是網路I/O的讀寫,請求的接收和回復 時間事件就是單次/多次執行的定時器,如主從復制、定時洗掉過期資料、字典rehash等 redis所有核心功能都是跑在主執行緒中的,像aof檔案落盤操作是在子執行緒中執行的,那么在高并發情況下它是怎么做到高性能的呢? 由于這兩種事件在同一個執行緒中執行,就會出現互相影響的問題,如時間事件到了還在等待/執行檔案事件,或者檔案事件已經就緒卻在執行時間事件,這就是單執行緒的缺點,所以在實作上要將這些影響降到最低,那么redis是怎么實作的呢?   定時執行的時間事件保存在一個鏈表中,由于鏈表中任務沒有按照執行時間排序,所以每次需要掃描單鏈表,找到最近需要執行的任務,時間復雜度是O(N),redis敢這么實作就是因為這個鏈表很短,大部分定時任務都是在serverCron方法中被呼叫,從現在開始到最近需要執行的任務的開始時間,時長定位T,這段時間就是屬于檔案事件的處理時間,以epoll為例,執行epoll_wait最多等待的時長為T,如果有就緒任務epoll會回傳所有就緒的網路任務,存在一個陣列中,這時我們知道了所有就緒的socket和對應的事件(讀、寫、錯誤、掛斷),然后就可以接收資料,決議,執行對應的命令函式, 如果最近要執行的定時任務時間已經過了,那么epoll就不會阻塞,直接回傳已經就緒的網路事件,即不等待, 總之單執行緒,定時事件和網路事件還是會互相影響的,正在處理定時事件網路任務來了,正在處理網路事件定時任務的時間到了,所以redis必須保證每個任務的處理時間不能太長,   redis處理流程如下: 1:服務啟動,開始網路埠監聽,等待客戶端請求 2:客戶端想服務端發起連接請求,創建客戶端連接物件,完成連接 3:將socket資訊注冊到epoll,設定超時時間為時間事件的周期時長,等待客戶端發起請求 4:客戶端發起操作資料庫請求(如GET) 5:epoll收到客戶端的請求,可能多個,按照順序處理請求 6:接收請求引數,接收完成后決議請求協議,得到請求命令 7:執行請求命令,即操作redis資料庫 8:將結果回傳給客戶端   1:redis哪些地方用到了多執行緒,哪些地方是單執行緒? Redis多執行緒和單執行緒模型對比如下圖:   從上圖中可以看出只有以下3個地方用的是多執行緒,其他地方都是單執行緒: 1:接收請求引數 2:決議請求引數 3:請求回應,即將結果回傳給client 很明顯以上3點各個請求都是互相獨立互不影響的,很適合用多執行緒,特別是請求體/回應體很大的時候,更能體現多執行緒的威力,而操作資料庫是請求之間共享的,如果使用多執行緒的話適合讀寫鎖,而操作資料庫本身是很快的(就是對map的增刪改查),單執行緒不一定就比多執行緒慢,當然也有可能是作者偷懶,懶得實作罷了,但這次的多執行緒模型還是值得我們學習一下的,   2:redis多執行緒是怎么實作的? 先大致說一下多執行緒的流程: 1:服務器啟動時啟動一定數量執行緒,服務啟動的時候可以指定執行緒數,每個執行緒對應一個佇列(list *io_threads_list[128]),最多128個執行緒, 2:服務器收到的每個請求都會放入全域讀佇列clients_pending_read,同時將佇列中的元素分發到每個執行緒對應的佇列io_threads_list中,這些作業都是在主執行緒中執行的, 3:每個執行緒(包括主執行緒和子執行緒)接收請求引數并做決議,完事后在client中設定一個標記CLIENT_PENDING_READ,標識引數決議完成,可以操作資料庫了,(主執行緒和子執行緒都會執行這個步驟) 4:主執行緒遍歷佇列clients_pending_read,發現設有CLIENT_PENDING_READ標記的,就操作資料庫 5:操作完資料庫就是回應client了,回應是一組函式addReplyXXX,在client中設定標記CLIENT_PENDING_WRITE,同時將client加入全域寫佇列clients_pending_write 6:主執行緒將全域佇列clients_pending_write以輪訓的方式將任務分發到每個執行緒對應的佇列io_threads_list 7:所有執行緒將遍歷自己的佇列io_threads_list,將結果發送給client   3:redis多執行緒是怎么做到無鎖的? 上面說了多執行緒的地方都是互相獨立互不影響的,但是每個執行緒的佇列就存在兩個兩個執行緒訪問的情況:主執行緒向佇列中寫資料,子執行緒消費,redis的實作有點反直覺,按正常思路來說,主執行緒在往佇列中寫資料的時候加鎖;子執行緒復制佇列&并將佇列清空,這個兩個動作是加鎖的,子執行緒消費復制后的佇列,這個程序是不需要加鎖的,按理來說主執行緒和子執行緒的加鎖動作都是非常快的,但是redis并沒有這么實作,那么他是怎么實作的呢?   redis多執行緒的模型是主執行緒負責搜集任務,放入全域讀佇列clients_pending_read和全域寫佇列clients_pending_write,主執行緒在將佇列中的任務以輪訓的方式分發到每個執行緒對應的佇列(list *io_threads_list[128]) 1:一開始子執行緒的佇列都是空,主執行緒將全對佇列中的任務分發到每個執行緒的佇列,并設定一個佇列有資料的標記(_Atomic unsigned long io_threads_pending[128]),io_threads_pending[1]=5表示第一個執行緒的佇列中有5個元素 2:子執行緒死回圈輪訓檢查io_threads_pending[index] > 0,有資料就開始處理,處理完成之后將io_threads_pending[index] = 0,沒資料繼續檢查 3:主執行緒將任務分發到子執行緒的佇列中,自己處理自己佇列中的任務,處理完成后,等待所有子執行緒處理完所有任務,繼續收集任務到全域佇列,在將任務分發給子執行緒,這樣就避免了主執行緒和子執行緒同時訪問佇列的情況,就必須加鎖了,因為任務是平均分配到每個佇列的,所以每個佇列的處理時間是接近的,等待的時間會很短,    4:原始碼執行流程 為了方便你看原始碼,這里加上一些代碼的執行流程 啟動socket監聽,注冊連接處理函式,連接成功后創建連接物件connection,創建client物件,通過aeCreateFileEvent注冊client的讀事件
main -> initServer -> acceptTcpHandler -> anetTcpAccept -> anetGenericAccept -> accept(獲取到socket連接句柄)
connCreateAcceptedSocket -> connCreateSocket -> 創建一個connection物件
acceptCommonHandler -> createClient創建client連接物件 -> connSetReadHandler -> aeCreateFileEvent -> readQueryFromClient

main -> aeMain -> aeProcessEvents -> aeApiPoll(獲取可讀寫的socket) -> readQueryFromClient(如果可讀) -> processInputBuffer -> processCommandAndResetClient(多執行緒下這個方法在當前流程下不會執行,而由主執行緒執行) 

在多執行緒模式下,readQueryFromClient會將client資訊加入server.clients_pending_read佇列,listAddNodeHead(server.clients_pending_read,c);   主執行緒會將server.clients_pending_read中的資料分發到子執行緒的佇列(io_threads_list)中,子執行緒會呼叫readQueryFromClient就行引數決議,主執行緒分發完任務后,會執行具體的操作資料庫的命令,這塊是單執行緒 如果引數決議完成會在client->flags中加一個標記CLIENT_PENDING_COMMAND,在主執行緒中先判斷client->flags & CLIENT_PENDING_COMMAND > 0,說明引數決議完成,才會呼叫processCommandAndResetClient,之前還擔心如果子執行緒還在做引數決議,主執行緒就開始執行命令難道不會有問題嗎?現在一切都清楚了
main -> aeMain -> aeProcessEvents -> beforeSleep -> handleClientsWithPendingReadsUsingThreads -> processCommandAndResetClient -> processCommand -> call

讀是多次讀:socket讀緩沖區有資料,epoll就會一直觸發讀事件,所以讀可能是多次的 寫是一次寫:往socket寫資料是在子執行緒中執行的,直接回圈直到資料寫完位置,就算某個執行緒阻塞了,也不會像單執行緒那樣導致所有任務都阻塞
執行完相關命令后,就是將結果回傳給client,回復client是一組函式,我們以addReply為例,說一下執行流程,執行addReply還是單執行緒的,將client資訊插入全域佇列server.clients_pending_write,
addReply -> prepareClientToWrite -> clientInstallWriteHandler -> listAddNodeHead(server.clients_pending_write,c)

在主執行緒中將server.clients_pending_write中的資料以輪訓的方式分發到多個子執行緒中
beforeSleep -> handleClientsWithPendingWritesUsingThreads -> 將server.clients_pending_write中的資料以輪訓的方式分發到多個執行緒的佇列中io_threads_list
list *io_threads_list[IO_THREADS_MAX_NUM];是陣列雙向鏈表,一個執行緒對應其中一個佇列

子執行緒將client中的資料發給客戶端,所以是多執行緒
server.c -> main -> initThreadedIO(啟動一定數量的執行緒) -> IOThreadMain(執行緒執行的方法) -> writeToClient -> connWrite -> connSocketWrite

網路操作對應的一些方法,所有connection物件的type欄位都是指向CT_Socket

ConnectionType CT_Socket = {
    .ae_handler = connSocketEventHandler,
    .close = connSocketClose,
    .write = connSocketWrite,
    .read = connSocketRead,
    .accept = connSocketAccept,
    .connect = connSocketConnect,
    .set_write_handler = connSocketSetWriteHandler,
    .set_read_handler = connSocketSetReadHandler,
    .get_last_error = connSocketGetLastError,
    .blocking_connect = connSocketBlockingConnect,
    .sync_write = connSocketSyncWrite,
    .sync_read = connSocketSyncRead,
    .sync_readline = connSocketSyncReadLine
};

 

   

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/227699.html

標籤:其他

上一篇:太贊了!首發獨家Java飛滴專案實戰視頻教程!可以讓你寫到簡歷上的專案, 限時分享!

下一篇:Elasticsearch搜索資料匯總

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more