溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Redis怎么執(zhí)行命令

發(fā)布時(shí)間:2021-07-10 14:11:39 來源:億速云 閱讀:128 作者:chen 欄目:大數(shù)據(jù)

本篇內(nèi)容介紹了“Redis怎么執(zhí)行命令”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

處理新連接

Redis在initServer()函數(shù)中創(chuàng)建循環(huán)事件調(diào)用了acceptTcpHandler和acceptUnixHandler函數(shù)(都在networking.c文件中)來處理接收到的TCP連接和Unix的Sockets連接。這兩個(gè)函數(shù)又調(diào)用了acceptCommonHandler()函數(shù),在這個(gè)函數(shù)中調(diào)用了createClient()函數(shù)創(chuàng)建一個(gè)新的client對象,用來表示一個(gè)新的客戶端連接。

createClient()函數(shù)具體做了哪些事情呢?

首先為變量c分配了內(nèi)存,接著將Socket連接置為非阻塞狀態(tài),并且設(shè)置了TCP無延遲。然后創(chuàng)建了File循環(huán)事件(aeCreateFileEvent)來調(diào)用readQueryFromClient函數(shù)。新建的客戶端默認(rèn)連接的是服務(wù)器的第一個(gè)數(shù)據(jù)庫(編碼為0),最后需要設(shè)置好客戶端的各種屬性和狀態(tài)。

讀一個(gè)客戶端的命令

剛剛我們提到了readQueryFromClient函數(shù),從名稱上就能看出來這個(gè)函數(shù)是用來從客戶端讀取命令的。下面來看看函數(shù)的具體實(shí)現(xiàn)。

Redis會先將命令讀入緩沖區(qū),一次最多讀取的大小是PROTO_IOBUF_LEN(1024*16)bit。然后調(diào)用processInputBufferAndReplicate()函數(shù),來處理緩沖區(qū)中的數(shù)據(jù),如果客戶端是master(主從同步過程),那么Redis會計(jì)算處理前后緩沖區(qū)的不同部分,以確定從節(jié)點(diǎn)接收了多少數(shù)據(jù)。processInputBufferAndReplicate()函數(shù)會處理客戶端向服務(wù)器發(fā)送命令和主節(jié)點(diǎn)向從節(jié)點(diǎn)發(fā)送命令這兩種情況,不過最后都需要調(diào)用processInputBuffer()函數(shù)。

processInputBuffer()函數(shù)會先判斷客戶端是否正常,如果出現(xiàn)連接中斷或者客戶端阻塞等情況,就會立即停止處理命令,不做無用功。然后根據(jù)讀取的請求生成相應(yīng)的Redis可以執(zhí)行的命令(包括參數(shù))。不同的請求類型分別調(diào)用processInlineBuffer()和processMultibulkBuffer()函數(shù)。生成好命令之后,交給processCommand()(server.c文件中)函數(shù)執(zhí)行,如果返回C_OK則重置客戶端,等待下一個(gè)命令。如果返回的是C_ERR,則客戶端會被銷毀(比如執(zhí)行QUIT命令)。

processCommand()函數(shù)會從Redis啟動時(shí)加載的命令表中查找命令,然后檢查命令的執(zhí)行權(quán)限。

如果是cluster,這時(shí)會判斷key是否屬于當(dāng)前的master,不屬于需要返回重定向信息。

如果內(nèi)存不夠用,這里也需要判斷一下是否有可以釋放的內(nèi)存,如果沒有,就不能執(zhí)行命令,返回錯(cuò)誤信息。

接下來會判斷一些不能接收寫命令的情況:

  • 服務(wù)器不能進(jìn)行持久化

  • 作為master,沒有足夠的可用的slave

  • 此服務(wù)器為只讀的slave,只有它的master可以接收寫命令

在訂閱模式中,只能接收指定的命令:(P)SUBSCRIBE / (P)UNSUBSCRIBE / PING / QUIT。

當(dāng)slave和master失聯(lián)時(shí),只能接收有flag "t"的命令,例如,INFO,SLAVEOF等。

如果命令沒有CMD_LOADING標(biāo)志,并且當(dāng)前服務(wù)器正在加載數(shù)據(jù),則不能接收此命令。

對lua腳本的長度進(jìn)行限制。

進(jìn)行完上面的各種條件判斷之后,才可以真正開始調(diào)用call()函數(shù)執(zhí)行命令。

執(zhí)行命令并返回

call()函數(shù)的參數(shù)是client類型的,取出cmd成員進(jìn)行執(zhí)行。

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;

如果是寫命令,就會使服務(wù)器變“臟”,也就是服務(wù)器需要標(biāo)記一下內(nèi)存中的某些頁有了改變。這對于Redis的持久化來說非常重要,它可以知道這個(gè)命令影響了多少個(gè)key。命令執(zhí)行完之后并沒有結(jié)束,call函數(shù)還會做一些其他操作。例如記錄日志,寫AOF文件,向從節(jié)點(diǎn)同步命令等。

至于返回值,每個(gè)命令有各自的處理方法,我們后面在介紹。

到這里,Redis處理命令的過程也就完成了。

后面我們會再通過具體的命令來對這個(gè)過程做一個(gè)更清晰的介紹。

“Redis怎么執(zhí)行命令”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI