上一篇 擴展Redis:增長Redis命令 講了如何動手編寫一個命令,但沒有具體講代碼的細節,今天講下Redis代碼中的經常使用數據結構和函數,看完這篇文章但願你們本身能寫一個helloworld的命令。 redis
首先講下環境,代碼的版本仍是3.2.11的。 sql
1、數據結構數據庫
一、robj緩存
robj是Redis源碼中用的很是多的數據結構,包括咱們輸入的命令和參數在服務端都是以robj來表示的。數據結構
typedef struct redisObject {
其中比較重要的是type和ptr字段,type表示數據的類型,經常使用類型有:函數
#define OBJ_STRING 0
全部客戶端輸入過來的參數都是STRIGN類型,即咱們輸入命令:spa
set key value設計
則服務端會生成3個robj對象,每一個的type都是 OBJ_STRING。3d
能夠參考typeCommand的代碼:指針
void typeCommand(client *c) {
還有一個重要的字段是ptr,這是一個void類型,便可以表明任何類型,若是是type爲OBJ_STRING,則ptr是一個char*的指針。
另外就是encoding字段了,上面發現全部基本類型是字符串,若是要表示整型怎麼辦呢,就是經過encoding幫忙了,能夠看下代碼:
int isObjectRepresentableAsLongLong(robj *o, long long *llval) {
二、client
client結構表明一個鏈接,固然一個從Redis也是一個鏈接,因此這個結構有從的一些信息:
/* With multiplexing we need to take per-client state.
整個結構體字段比較多,重點關注如下幾塊:
argc:參數個數
argv:具體一個個的參數
db:當前選擇的數據庫
argv[0]表示咱們的命令,後面就是命令具體的參數了,若是咱們輸入命令:
set name ljh
則:
c->argv[0]表示set命令,type爲OBJ_STRING,ptr是一個char*;
c->argv[1]表示參數name,type爲OBJ_STRING,ptr是一個char*;
c->argv[2]表示參數ljh,type爲OBJ_STRING,ptr是一個char*;
經過解析c->argv參數,咱們就能夠獲得一個個的參數進行驗證和處理了。
2、經常使用函數
一、addReplyError
通常表示執行遇到錯誤,返回客戶端一個錯誤;
這個函數有2個參數,第一個是一個client的指針,第二個爲錯誤字符串:
addReplyError(c,"increxpire command maxNum param must bigger or equal than 0");
二、addReply
向輸出緩存區增長內容;
有2個參數,第一個也是一個client的指針,第二個是一個robj的指針:
addReply(c,shared.colon);
上面是上一篇擴展命令裏的代碼,若是O的type爲OBJ_STRIGN,而且encoding是OBJ_ENCODING_INT,值爲5,這裏表示向客戶端輸出如下內容:
:5\r\n
這裏講下Redis協議,響應這塊的協議以下:
狀態回覆(status reply)的第一個字節是 「+」
錯誤回覆(error reply)的第一個字節是 「-「
整數回覆(integer reply)的第一個字節是 「:」
批量回復(bulk reply)的第一個字節是 「$」
多條批量回復(multi bulk reply)的第一個字節是 「*」
由於咱們的incexpire返回一個整型數字,因此先是:,而後是數字,最後是表示結束的換行和回車。
三、lookupKey
相關的還有lookupKeyRead,lookupKeyWrite,這幾個函數都是表示從某個庫裏查找相應的key,帶寫的函數會先判斷是否過時;
第一個是redisDb結構,第二個是一個robj*,表示要查找哪一個key;
當前鏈接的數據庫能夠經過 c->db來獲取。
四、createStringObjectFromLongLong
這些是建立相應類型robj的命令,有的時候咱們要根據一些處理結果返回字符串或數值給客戶端,前面講了大部分函數都接受robj做爲參數,像添加內容到輸入緩存區的addReply;
其它的命令有:
createStringObject:根據字符串建立robj
createStringObjectFromLongDouble:根據double建立robj
3、調試
你們看完上面代碼想本身寫個命令呢,按上面講的基本上能夠把環境跑起來,最後就是調試了,能夠下個gdb,而後在相應的函數上打斷點就能夠了,經常使用命令以下:
break 函數名
print 變量名
上面兩個命令應該是最經常使用的了,第一個是下斷點,第二個是打印變量的值。