您好,登錄后才能下訂單哦!
本篇內容介紹了“Redis怎么執行命令”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
Redis在initServer()函數中創建循環事件調用了acceptTcpHandler和acceptUnixHandler函數(都在networking.c文件中)來處理接收到的TCP連接和Unix的Sockets連接。這兩個函數又調用了acceptCommonHandler()函數,在這個函數中調用了createClient()函數創建一個新的client對象,用來表示一個新的客戶端連接。
createClient()函數具體做了哪些事情呢?
首先為變量c分配了內存,接著將Socket連接置為非阻塞狀態,并且設置了TCP無延遲。然后創建了File循環事件(aeCreateFileEvent)來調用readQueryFromClient函數。新建的客戶端默認連接的是服務器的第一個數據庫(編碼為0),最后需要設置好客戶端的各種屬性和狀態。
剛剛我們提到了readQueryFromClient函數,從名稱上就能看出來這個函數是用來從客戶端讀取命令的。下面來看看函數的具體實現。
Redis會先將命令讀入緩沖區,一次最多讀取的大小是PROTO_IOBUF_LEN(1024*16)bit。然后調用processInputBufferAndReplicate()函數,來處理緩沖區中的數據,如果客戶端是master(主從同步過程),那么Redis會計算處理前后緩沖區的不同部分,以確定從節點接收了多少數據。processInputBufferAndReplicate()函數會處理客戶端向服務器發送命令和主節點向從節點發送命令這兩種情況,不過最后都需要調用processInputBuffer()函數。
processInputBuffer()函數會先判斷客戶端是否正常,如果出現連接中斷或者客戶端阻塞等情況,就會立即停止處理命令,不做無用功。然后根據讀取的請求生成相應的Redis可以執行的命令(包括參數)。不同的請求類型分別調用processInlineBuffer()和processMultibulkBuffer()函數。生成好命令之后,交給processCommand()(server.c文件中)函數執行,如果返回C_OK則重置客戶端,等待下一個命令。如果返回的是C_ERR,則客戶端會被銷毀(比如執行QUIT命令)。
processCommand()函數會從Redis啟動時加載的命令表中查找命令,然后檢查命令的執行權限。
如果是cluster,這時會判斷key是否屬于當前的master,不屬于需要返回重定向信息。
如果內存不夠用,這里也需要判斷一下是否有可以釋放的內存,如果沒有,就不能執行命令,返回錯誤信息。
接下來會判斷一些不能接收寫命令的情況:
服務器不能進行持久化
作為master,沒有足夠的可用的slave
此服務器為只讀的slave,只有它的master可以接收寫命令
在訂閱模式中,只能接收指定的命令:(P)SUBSCRIBE / (P)UNSUBSCRIBE / PING / QUIT。
當slave和master失聯時,只能接收有flag "t"的命令,例如,INFO,SLAVEOF等。
如果命令沒有CMD_LOADING標志,并且當前服務器正在加載數據,則不能接收此命令。
對lua腳本的長度進行限制。
進行完上面的各種條件判斷之后,才可以真正開始調用call()函數執行命令。
call()函數的參數是client類型的,取出cmd成員進行執行。
1/* Call the command. */
2dirty = server.dirty;
3start = ustime();
4c->cmd->proc(c);
5duration = ustime()-start;
6dirty = server.dirty-dirty;
7if (dirty < 0) dirty = 0;
如果是寫命令,就會使服務器變“臟”,也就是服務器需要標記一下內存中的某些頁有了改變。這對于Redis的持久化來說非常重要,它可以知道這個命令影響了多少個key。命令執行完之后并沒有結束,call函數還會做一些其他操作。例如記錄日志,寫AOF文件,向從節點同步命令等。
至于返回值,每個命令有各自的處理方法,我們后面在介紹。
到這里,Redis處理命令的過程也就完成了。
后面我們會再通過具體的命令來對這個過程做一個更清晰的介紹。
“Redis怎么執行命令”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。