亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

redis學習筆記(一)

2024-07-21 02:51:19
字體:
來源:轉載
供稿:網友

redis 學習筆記(一)

1.adlist.h

準備花點時間將redis的源代碼從頭到尾學習一邊,一邊鍛煉自己讀代碼的能力,一邊學習大牛們是如何寫出來漂亮的代碼,而且能從底層代碼實現中將自己一直以來欠缺的那一部分知識體系補全,所以準備從redis入手,再學習apache thrift,我想等都學習完一遍之后,能夠將自己工作一年半以來零碎的一些知識技能變得更加系統化一點

redis源碼中分為結構體,數據操作,工具,事件,基本信息,兼容,主程序,網絡,封裝類等,我準備從最基礎的結構體入手,大致的看了一下,redis的結構體基本上基于list和hash,一個一個順著學吧,今天就是adlist了

結構體:

typedef struct listNode{

struct listNode *PRev;//指向前一個節點

struct listNode *next;//指向后一個節點

void *value;//node值的指針

} listNode;

第一個結構體應該定義的是鏈表的節點,從結構體的內容可以猜測adlist是一個雙向列表,prev是指向前一個節點的指針,next是指向后一個節點的指針,而value暫時不知道是干什么的

typedef struct listIter{

listNode *next;//指向當前迭代位置的下一個節點,隨迭代器方向而變化

int direction;//迭代器的方向

}listIter;

從名字來看,第二個結構體應該是一個迭代器,那么next便是指向下一個節點,direction從字面意思應該是迭代器的方向,由于list是一個雙向鏈表,那么可以猜測listIter可以實現正向迭代器和反向迭代器,相比于C++的iterator基類,這應該是用C實現的一個簡易的迭代器了

typedef struct list{

listNode *head;//頭節點

listNode *tail;//尾節點

void *(*dup)(void *ptr);//復制函數指針

void (*free)(void *ptr);//釋放函數指針

int (*match)(void *ptr, void *key);//匹配函數指針

unsigned long len;//鏈表長度

}list;

結構體list應該就是一個雙向列表,head是頭節點,tail是尾節點,然后dup,free和match應該就是C風格的list的成員函數,len是鏈表的長度

從adlist.h文件里面定義了如下函數,從字面分析其實現:

list *listCreate(void);//創建list

void listRelease(list *list);//列表釋放

list *listAddNodeHead(list *list, void *value);//從頭部增加節點

list *listAddNodeTail(list *list, void *value);//從尾部增加節點

list *listInsertNode(list *list, listNode *old_node, void *value,int after);//隨機插入節點

void listDelNode(list *list, listNode *node);//刪除節點

listIter *listGetIterator(list *list, int direction);//獲取迭代器,返回一個listIter結構體指針

listNode *listNext(listIter *iter); //獲取下個節點

void listReleaseIterator(listIter *iter);//釋放迭代器指針

list *listDup(list *orig); //列表復制

listNode *listSearchKey(list *list, void *key);//在list中查找key,并返回節點

listNode *listIndex(list *list, long index);//根據索引查找節點

void listRewind(list *list, listIter *li);//重置迭代器

void listRewindTail(list *list, listIter *li);//從尾部重置迭代器

void listRotate(list *list);//將鏈表的尾節點置于隊首

此外,在adlist.h中定義了一系列的宏定義,不再一一列述,不過學習了程序員大牛們的編碼習慣,適當的定義宏使得代碼變得更易讀

再看adlist.c中對于函數的具體實現(感覺看完之后,把大學學鏈表的時候的C實現撿回來了…):

//返回一個list結構體指針

list *listCreate(void){

//聲明一個list結構體

struct list *list;

//為list結構體分配內存,zmalloc是redis文件下面zmalloc.h里面定義的方法,跳過去看了一下,看不懂,里面很多宏定義,想想以前看別人代碼就是懶得看些,所以賴著性子看看

/*

void *zmalloc(size_t size){

//上文中宏PREFIX_SIZE為0,為ptr分配了一個size大小的內存空間,size_t的實現代碼為typedef unsigned int size_t;

void *ptr = malloc(size + PREFIX_SIZE);

if(!ptr) zmalloc_oom_handler(size);//如果ptr為NULL,返回錯誤,abort

#ifdef HAVE_MALLOC_SIZE//上文定義

//返回所申請的內存空間

update_zmalloc_stat_alloc(zmalloc_size(ptr));

return ptr;

}

*/

if((list = zmalloc(sizeof(*list))) == NULL) return NULL;

//將頭節點和尾節點都置為NULL

list->head = list->tail = NULL;

//將鏈表長度置為0

list->len = 0;

//將struct的成員函數指針置為NULL

list->dup = NULL;

list->free = NULL;

list->match  = NULL;

//返回一個空的list指針

return list;

}

void listRelease(list *list){

unsigned long len;

listNode *current, *next;//兩個節點指針,一個指向當前節點,一個指向下一個節點

current = list->head;//將起點置在隊首

len = list->len;

//遍歷鏈表

while(len—){

//next為current所指向的下一個節點

next = current->next;

//判斷鏈表是否有free方法,調用free方法,釋放listNode的value函數指針,這里并不是很清楚value是干什么的,我理解可能在其他文件里面有實現

if(list->free) list->free(current->value);

//調用zmalloc.h中的zfree方法釋放掉current指針

zfree(current);

//指針后移

current = next;

}

//釋放鏈表指針

zfree(list);

}//個人認為這里可以每次釋放一個node,便使list->len—,且重置head指針,這樣如果循環釋放到一半程序崩潰的話,還能保證鏈表的完整性

 繼續往下看

void *listAddNodeHead(list *list, void* value){

listNode *node;

//分配內存檢查

if((node = zmalloc(sizeof(*node))) == NULL)return NULL;

//這里理解了value的含義,在node中設置為void*是為了適配不同指針類型,然后value就是node的值的指針類型

node->value = value;

//如果鏈表為空,那么插入的節點就是鏈表的唯一一個節點,由于是雙向鏈表,所以需要注意前后指針的重置

if(list->len == 0){

list->head = list->tail = node;

node->prev = node->next = NULL;

} else{//如果不是空,那么就在鏈表最前面插入,然后置新節點為head

node->prev = NULL;

node->next = list->head;

list->head->prev = node;

list->head = node;

}

//鏈表長度加1

list->len ++;

return list;

}

//功能與上面類似,只不過實現的是在鏈表尾部添加

void *listAddNodeTail(list *list, void *value){

listNode *node;

if((node = zmalloc(sizeof(*node))) == NULL) return NULL;

node->value = value;

if(list->len = 0){

list->head = list->tail = node;

node->prev = node->next = NULL;

} else{

node->prev = list->tail;

node->next = NULL;

list->tail->next = node;

list->tail = node;

}

list->len ++;

return list;

}

// old_node應該指的是目標節點,after應該是指是否在后面插入

void *listInsertNode(list *list, listNode *old_node, void *value, int after){

listNode *node;

//如果新節點分配內存失敗,返回null

if((node = zmalloc(sizeof(*node))) == NULL)return NULL;

//為新節點的value賦值

node->value = value;

//如果是在目標節點身后插入,那么要注意移動目標節點的next指針

if(after){

node->prev = old_node;

node->next = old_node->next;

//我覺得如果是我在寫代碼會遺漏這一個條件判斷,如果是尾節點,那么需要重置list的尾指針位置

if(list->tail = old_node){

list->tail = node;

}

}else{//如果在前插入,與上面相反

node->next = old_node;

node->prev = old_node->prev;

if(list->head = old_node){

list->head = node;

}

}

//檢查新節點的前后指針是否連接,

if(node->prev != NULL){

node->prev->next = node;

}

if(node->next != NULL){

node->next->prev = node;

}

lits->len++;

return list;

}

void listDelNode(list *list, listNode *node){

//判斷如果目標節點有前置指針,那么使前節點指向目標節點的身后

if(node->prev){

node->prev->next = node->next;

}else{//如果目標節點是頭指針,那么直接標識next為頭部(我寫代碼絕對寫不得這樣簡潔易懂)

list->head = node->next;

}

//處理尾部,與上文類似

if(node->next){

node->next->prev = node->prev;

}else{

list->tail = node->prev;

}

//處理前后節點是相互獨立的,這樣寫就不用單獨將首尾列出來處理一遍

if(list->free) list->free(node->value);

//釋放節點

zfree(node);

list->len—;

}

//獲取一個list迭代器指針

listiter *listGetIteraor(list *list, int dirction){

//申明一個迭代器指針

listIter *iter;

//判斷內存分配,人家每一個臨界條件都注意得特別好

if((iter = zmalloc(sizeof(*iter))) == NULL) return NULL;

//判斷方向,如果dire為0,那么從頭開始遍歷

if(direction == AL_START_HEAD) iter->next = list->head;

//如果是1,從尾部開始

else iter->next = list->tail;

iter->direction  = direction;

return tier;

} //迭代器區別與listNode,所以這里的iter->next可以理解為存在于list維度之外的一層

void listReleaseIterator(listIter *iter){

zfree(iter);//zfree封裝了redis自己的free方法,free方法只釋放用malloc或者alloc操作分配的內存

}

//對一個迭代器指針的重置操作,但是迭代器必須先初始化,這個函數置首部

void listRewind(list *list, listIter *li){

li->next = list->head;

li->direction = AL_START_HEAD;

}

//置尾部

void listRewindTail(list *list, listIter *li){

li->next = list->tail;

li->direction = AL_START_TAIL;

}

//獲取迭代器指向的節點

listNode *listNext(listIter *iter){

//這里迭代器指向的某一個節點

listNode *current = iter->next;

//判斷節點的合法性,并是迭代器移動

if(current != NULL){

if(iter->direction == AL_START_HEAD)

iter->next = current->next;

else

iter->next = current->prev;

}

return current;

} //我理解這里其實是實現了C++ Iterator中iterator++/—的操作

//鏈表的復制操作

list *listDup(list *orig){

list *copy;//復制后的指針

listIter iter;//迭代器指針

listNode *node;

//判斷copy是否創建成功

if((copy = listCreate()) == NULL)return NULL;

//復制相關函數指針

copy->dup = orig->dup;

copy->free = orig->free;

copy->match = orig->match;

//迭代器置首部

listRewind(orig, &iter);

//在C++里面相當于iter++!=list.end();

while((node = listNext(&iter)) != NULL){

void *value;

if(copy->dup){

value = copy->dup(node->value);

if(value == NULL){

listRelease(copy);

return NULL;

}

}else

value = node->value;

//從新鏈表的尾部開始插入節點

if(listAddNodeTail(copy, value) == NULL){

listRelease(copy);

return NULL;

}

}

//返回新的鏈表

return copy;

}

//一個雙向鏈表的查詢操作,自己也寫過無數遍,感覺就是沒有別人寫得清楚

listNode *listSearchKey(list *list, void *key){

listIter iter;

listNode *node;

//首部迭代器

listRewind(list, &iter);

//同樣的一個迭代器向后迭代的操作

while((node = listNex(&iter)) != NULL){

//調用了match方法,這里用了這么多函數指針我理解為redis可能有很多的數據類型是基于list實現的,所以根據不同的類型實現了不同的方法

if(list->match){

if(list->match(node->value, key)){

return node;

}

}else{//簡單的比較

if(key == node->value){

return node;

}

}

}

return NULL;

}

//這個函數看了幾遍才看懂,而且是看了英文注釋,感覺英文水平飆升…根據index查找節點,正數從前往后,負數從后往前

listNode *listIndex(list *list, long index){

listNode *n;

//負數,從尾部開始遍歷

if(index < 0){

index = (-index)-1;

n = list->tail;

while(index— && n) n = n->prev;

}else{

n = list>head;

while(index— && n) n = n->next;

}

return n;

} // 想當于給一個非順序存儲的鏈表給了一個根據下標查找的操作

將鏈表尾部放在首部前面

void listRotate(list *list){

//定義尾部

listNode *tail = list->tail;

// 如果長度是1,那么尾部就是首部,無意義

if(listLength(list) <= 1)return;

//將尾部重置為之前尾部的prev

list->tail = tail->prev;

list->tail->next = NULL;

//將之前的尾部放在list->head之前作為list的首部

list->head->prev = tail;

tail->prev = NULL;

tail->next = list->head;

list->head = tail;

}

總結: 1.回顧了list鏈表的一些底層操作代碼,順帶的一下子將例如棧,隊列,以及二叉樹的操作回憶了一遍;

2.無腦的用C++的庫用多了之后,都完全覺得所有的組件方法等天生就有,然而現在重新改變了這一個觀點,任何邏輯操作都是代碼寫出來的,底層的也好,業務層也好;

3.多學習別人的代碼果然很有好處,雖然在這一章感覺閱讀難度不大,但是對于編碼習慣也好,還是思維也好,給自己有一定的沖擊,先易后難,希望自己堅持


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲高清不卡av| 欧美性视频精品| 一区二区欧美激情| 精品国产老师黑色丝袜高跟鞋| 久久精品亚洲国产| 欧美激情亚洲一区| 狠狠爱在线视频一区| 国产亚洲a∨片在线观看| 欧美超级乱淫片喷水| 日韩av快播网址| 九九精品在线播放| 久久不射热爱视频精品| 国产精品久久色| 九九视频直播综合网| 欧美性videos高清精品| 亚洲国产私拍精品国模在线观看| 91成人国产在线观看| 色哟哟网站入口亚洲精品| 国产精品久久久久久一区二区| 欧美日韩国产一区在线| 成人黄色在线观看| 中国china体内裑精亚洲片| 青草青草久热精品视频在线观看| 91久久精品视频| 国产精品永久免费| 成人午夜激情网| 色综合久久88色综合天天看泰| 亚洲国内精品在线| 欧美在线影院在线视频| 国产91精品网站| 亚洲欧美日韩精品久久亚洲区| 91高清视频免费| 在线播放亚洲激情| 亚洲毛片在线看| 国产精品白丝jk喷水视频一区| 日韩av电影在线网| 日本午夜精品理论片a级appf发布| 亚洲最大在线视频| 亚洲精品第一国产综合精品| 成人夜晚看av| 蜜臀久久99精品久久久久久宅男| 色综合久久精品亚洲国产| 26uuu另类亚洲欧美日本老年| 亚洲白虎美女被爆操| 欧美日韩国产影院| 亚洲精品视频中文字幕| 亚洲va码欧洲m码| 午夜精品久久久久久99热软件| 91精品久久久久久综合乱菊| 亚洲japanese制服美女| 亚洲大尺度美女在线| 九九九久久国产免费| 国产精品夫妻激情| 国产精品欧美激情| 久久久久一本一区二区青青蜜月| 午夜精品一区二区三区在线视频| 精品视频中文字幕| 亚洲一区www| 亚洲欧洲自拍偷拍| 亚洲一区二区久久久| 97视频在线观看成人| 国产一区二区丝袜高跟鞋图片| 色悠悠国产精品| 91精品国产综合久久久久久蜜臀| 91免费看视频.| 国产精品a久久久久久| 欧美丰满片xxx777| 一个色综合导航| 日韩福利视频在线观看| 7m精品福利视频导航| 亚洲欧美国产高清va在线播| 久久久久久国产精品久久| 国产免费久久av| 久久国内精品一国内精品| 亚洲片在线资源| 亚洲一区二区三区香蕉| 亚洲免费视频观看| 国产精品久久久久久av福利| 精品电影在线观看| 国产这里只有精品| 久久免费在线观看| 91精品在线观| 欧美成aaa人片在线观看蜜臀| 日韩免费高清在线观看| 国产精品人人做人人爽| 在线日韩第一页| 日韩成人中文字幕| 欧美电影《睫毛膏》| 午夜伦理精品一区| 欧美中文字幕第一页| 国产日韩精品在线播放| 日韩大片免费观看视频播放| 国产欧美在线看| 日韩中文字幕不卡视频| 国产精品偷伦一区二区| 中日韩美女免费视频网站在线观看| 亚洲国模精品私拍| 日韩免费视频在线观看| 欧美激情精品久久久久久| 日本成人激情视频| 亚洲va欧美va国产综合剧情| 中文字幕亚洲欧美日韩高清| 国产精品久久国产精品99gif| 欧美一区二区影院| 亚洲第一页自拍| 色播久久人人爽人人爽人人片视av| 91精品久久久久久久久久久久久| 日韩中文字幕久久| 国产成人综合av| 中文字幕日韩免费视频| 国产91精品最新在线播放| 成人精品福利视频| 国产一区二区免费| 久久777国产线看观看精品| 亚洲人a成www在线影院| 国产精品高潮粉嫩av| 亚洲精品福利免费在线观看| 亚洲曰本av电影| 欧美做受高潮电影o| 欧美成人午夜激情在线| 成人欧美一区二区三区黑人孕妇| 国产精品第一第二| www.亚洲一区| 欧美色视频日本高清在线观看| 日韩高清av一区二区三区| 国产精品视频区1| 欧美亚洲国产日本| 久久久久久久久久婷婷| 国产免费亚洲高清| 国产成人亚洲综合91精品| 日韩国产欧美精品一区二区三区| 国产91精品网站| 国产精品白丝jk喷水视频一区| 亚洲国产精品久久| 欧美高跟鞋交xxxxhd| 欧美日韩高清在线观看| 久久精品美女视频网站| 成人免费xxxxx在线观看| 中文字幕自拍vr一区二区三区| 欧美激情videos| 日韩免费看的电影电视剧大全| 日韩高清av一区二区三区| 92看片淫黄大片看国产片| 欧美富婆性猛交| 欧美精品在线网站| 91国产精品视频在线| 欧美尤物巨大精品爽| 黑人狂躁日本妞一区二区三区| 亚洲日韩欧美视频| 久久成人18免费网站| 亚洲qvod图片区电影| 欧美激情欧美狂野欧美精品| 亚洲一区二区在线播放| 日韩av毛片网| 国产一区二区成人| 色婷婷综合成人av| 亚洲精品天天看| 久久久国产精品亚洲一区| 欧美性猛交xxxx黑人猛交| 姬川优奈aav一区二区| 日韩av在线免费观看| 最近2019中文字幕第三页视频| 国产成人精品国内自产拍免费看| 2019中文字幕全在线观看|