Redis之客戶端

本文主要介紹Redis客戶端實現(xiàn),包括客戶端狀態(tài)快耿,與服務(wù)器的交互等內(nèi)容莫秆。

Redis是一對多服務(wù)器程序,通過使用由I/O多路復(fù)用技術(shù)實現(xiàn)的文件事件處理器极舔,Redis服務(wù)器使用單線程單進程的方式處理命令請求,并與多個客戶端進行網(wǎng)絡(luò)通信链瓦。

客戶端狀態(tài)由RedisClient結(jié)構(gòu)保存拆魏,服務(wù)器都為每個客戶端維持一個這樣的結(jié)構(gòu),其中包括的信息有:
· 客戶端的套接字描述符慈俯;
· 客戶端的名字渤刃;
· 指向客戶端正在使用的數(shù)據(jù)庫的指針,以及該數(shù)據(jù)庫的號碼贴膘;
· 客戶端當前要執(zhí)行的命令卖子、命令的參數(shù)、以及執(zhí)行命令實現(xiàn)函數(shù)的指針步鉴;
· 客戶端的輸入緩沖區(qū)與輸出緩沖區(qū)揪胃;
· 客戶端的復(fù)制狀態(tài)信息,以及進行復(fù)制所需的數(shù)據(jù)結(jié)構(gòu)氛琢;
· 客戶端執(zhí)行BRPOP喊递,BLPOP等列表阻塞命令時使用的數(shù)據(jù)結(jié)構(gòu);
· 客戶端的事務(wù)狀態(tài)阳似,以及執(zhí)行watch命令時使用的數(shù)據(jù)結(jié)構(gòu)骚勘;
· 客戶端執(zhí)行發(fā)布與訂閱功能時使用的數(shù)據(jù)結(jié)構(gòu);
· 客戶端的身份驗證標志撮奏;
· 客戶端的創(chuàng)建時間俏讹,與服務(wù)器最后一次通信時間,以及客戶端的輸出緩沖區(qū)大小超出軟性限制的時間畜吊。

Redis服務(wù)器狀態(tài)結(jié)構(gòu)的clients屬性是一個鏈表泽疆,這個鏈表保存了所有與服務(wù)器連接的客戶端的狀態(tài)結(jié)構(gòu),對客戶端執(zhí)行批量操作玲献,或者查找某個指定的客戶端殉疼,都可以通過遍歷client鏈表完成梯浪。

struct redisServer {
    // ...
    list *clients;

    // ...
};

下圖展示了這種結(jié)構(gòu):

I、客戶端屬性

1.1 套接字描述符

客戶端狀態(tài)的fd屬性記錄了客戶端正在使用的套接字描述符:

typedef struct redisClient {
    //... 
    int fd;
    //...
} redisClient;

偽客戶端的fd屬性為-1瓢娜,這包括載入AOF的偽客戶端以及用于執(zhí)行Lua腳本的偽客戶端挂洛。

普通客戶端的fd為大于-1 的整數(shù)。

執(zhí)行CLIENT list命令可以列出目前所有連接到服務(wù)器的普通客戶端眠砾。

1.2 名字

可以使用CLIENT setname命令為客戶端設(shè)置一個名字虏劲,名字保存在RedisClient的 那么屬性中。

1.3 標志

客戶端的標志屬性flags基類客戶端的角色褒颈,以及客戶端目前所處的狀態(tài)柒巫,存儲在redisClient的flags屬性中:
flags屬性可以是單個標志:flags = <flag>, 也可以是二進制多個標志: flags = <flag1> | <flag2> | ...

具體標志所表示的含義可以參見Redis文檔

1.4 輸入緩沖區(qū)

客戶端狀態(tài)的輸入緩沖區(qū)用于保存客戶端發(fā)送的命令請求:

typedef struct redisClient {
    //...
    sds querybuf;
    //...
} redisClient;  
1.5 命令與命令參數(shù)

在服務(wù)器將客戶端發(fā)送的命令請求保存到客戶端的querybuf屬性之后哈肖,服務(wù)器將對命令請求的內(nèi)容進行分析吻育,并將得出的命令參數(shù)以及命令參數(shù)的個數(shù)分別保存到客戶端狀態(tài)的argv屬性與argc屬性:

typedef struct redisClient {
    //...
    robj **argv;
    int argc;

    //...
} redisClient;  
1.6 命令的實現(xiàn)函數(shù)

當服務(wù)器從協(xié)議內(nèi)容中分析并得出argv和argc屬性之后念秧,服務(wù)器會根據(jù)argv[0]的值淤井,在命令表中查找所對應(yīng)的命令實現(xiàn)函數(shù)。

下圖為一個命令表示例:

當程序在命令表中成功找到argv[0]所對應(yīng)的RedisCommand結(jié)構(gòu)時摊趾,會將客戶端狀態(tài)的cmd指針指向這個結(jié)構(gòu)币狠。

之后,服務(wù)器使用cmd屬相所指向的命令結(jié)構(gòu)砾层,以及argv和argc中保存的信息漩绵,完成客戶端命令。

1.7 輸出緩沖區(qū)

執(zhí)行命令所得到的回復(fù)會被保存到客戶端狀態(tài)的輸出緩沖區(qū)中肛炮,每個客戶端都有兩個輸出緩沖區(qū)止吐,一個緩沖區(qū)的大小是固定的,另一個是可變的:
· 固定大小的緩沖區(qū)用于保存長度較小的回復(fù)侨糟,如OK等碍扔,其以數(shù)組形式存儲;
· 可變大小的緩沖區(qū)用于保存那些長度比較大的回復(fù)秕重,如很多元素的集合不同,以鏈表形式存儲;

typedef struct redisClient {
    //...
    char buf[REDIS_REPLY_CHUNK_BYTES];
    int bufpos;  

    list *reply;

    //...
} redisClient;

buf是一個固定大小緩沖區(qū)的數(shù)組溶耘,bufpos屬性記錄了buf數(shù)組目前使用的字節(jié)數(shù)量二拐。

reply鏈表是可變緩沖區(qū)。

II凳兵、客戶端的創(chuàng)建與關(guān)閉

2.1 創(chuàng)建普通客戶端

前面已經(jīng)說過百新,服務(wù)器通過client鏈表來維護客戶端,每次創(chuàng)建的新客戶端都會添加到鏈表末尾庐扫。

2.2 關(guān)閉客戶端

服務(wù)器會因為多種原因關(guān)閉客戶端饭望,這里重點說明服務(wù)器為限制客戶端輸出緩沖區(qū)大小而采取的關(guān)閉客戶端措施澜倦。

· 硬性限制:如果緩沖區(qū)大小超過了硬性限制所設(shè)置的大小,則服務(wù)器立即關(guān)閉客戶端杰妓。

· 軟性限制:如果輸出緩沖區(qū)大小超過了軟性限制所設(shè)置的大小藻治,但還沒超過影響限制,服務(wù)器使用一個time屬性來記錄客戶端到達軟性限制的時間巷挥,如果緩沖區(qū)的大小一直超出軟性限制桩卵,并持續(xù)時間超過設(shè)定的時長,則會關(guān)閉客戶端倍宾;如果在未到達時長之前雏节,不再超出軟性限制,客戶端就不會關(guān)閉高职。

2.3 偽客戶端

服務(wù)器中包含兩個不需要socket的偽客戶端钩乍,分別執(zhí)行AOF load,與lua腳本

【參考】
[1] 《Redis設(shè)計與實現(xiàn)》

歡迎轉(zhuǎn)載怔锌,轉(zhuǎn)載請注明出處Redis之客戶端

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末寥粹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子埃元,更是在濱河造成了極大的恐慌涝涤,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岛杀,死亡現(xiàn)場離奇詭異阔拳,居然都是意外死亡,警方通過查閱死者的電腦和手機类嗤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進店門糊肠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人遗锣,你說我怎么就攤上這事货裹。” “怎么了黄伊?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵泪酱,是天一觀的道長。 經(jīng)常有香客問我还最,道長墓阀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任拓轻,我火速辦了婚禮斯撮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扶叉。我一直安慰自己勿锅,他們只是感情好帕膜,可當我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著溢十,像睡著了一般垮刹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上张弛,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天荒典,我揣著相機與錄音,去河邊找鬼吞鸭。 笑死寺董,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的刻剥。 我是一名探鬼主播遮咖,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼造虏!你這毒婦竟也來了御吞?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤酗电,失蹤者是張志新(化名)和其女友劉穎魄藕,沒想到半個月后内列,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撵术,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年话瞧,在試婚紗的時候發(fā)現(xiàn)自己被綠了嫩与。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡交排,死狀恐怖划滋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情埃篓,我是刑警寧澤处坪,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站架专,受9級特大地震影響同窘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜部脚,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一想邦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧委刘,春花似錦丧没、人聲如沸鹰椒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽漆际。三九已至,卻和暖如春夺饲,著一層夾襖步出監(jiān)牢的瞬間灿椅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工钞支, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留茫蛹,地道東北人。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓烁挟,卻偏偏與公主長得像婴洼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子撼嗓,可洞房花燭夜當晚...
    茶點故事閱讀 45,585評論 2 359