redis 學習筆記一

來源:互聯網
上載者:User

標籤:blog   io   os   ar   for   strong   sp   div   on   

  找了半天,發覺還是redis的源碼看起來比較舒服。所以決定今年把redis的源碼讀一遍順便做個讀書筆記。好好記錄下。話說現在越來不越不願意用腦袋來記錄東西,喜歡靠note來記。話說這樣不愛用腦會不會過早的老年癡呆呢~~~

 

一、redis下載編譯

這裡沒什麼好說的

用的版本是redis-2.8.17

 

1)redis-server是可執行程式

2)mian函數在redis.c裡面

3)如果要修改調試 這屆在src目錄下   修改後make或者make clean;make 就行

 

從main函數說起這裡先說兩個部分一個是  redis裡面的回呼函數  還有一個是redis裡面的log日誌

二、redis裡的回呼函數

先看下代碼;這是把redis裡面的回呼函數拿出來修改下

/*redis裡的回呼函數*/#include<stdio.h>#include<stdlib.h>  static void zmalloc_default_oom(size_t size) {    printf("zmalloc_default_oom\n");    fprintf(stderr, "zmalloc: Out of memory trying to allocate %d bytes\n",size);    fflush(stderr);} static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom;  void zmalloc_set_oom_handler(void (*oom_handler)(size_t)) {    printf("zmalloc_set_oom_handler\n");    zmalloc_oom_handler = oom_handler;} void redisOutOfMemoryHandler(size_t allocation_size) {    printf("redisOutOfMemoryHandler------:%d\n",allocation_size);} int main(void){    //zmalloc_set_oom_handler(redisOutOfMemoryHandler);    zmalloc_oom_handler(10);    getchar();    return 0;}

  

運行結果

zmalloc_default_oom

zmalloc:Out of memory trying to allocate 10 bytes

 

我們可以看到預設情況下,在沒有註冊回呼函數的情況下zmalloc_oom_handler是指向  zmalloc_default_oom函數的

 

假如註冊了回呼函數的情況下,則調用的是 註冊了的回呼函數

int main(void){    zmalloc_set_oom_handler(redisOutOfMemoryHandler);    zmalloc_oom_handler(10);    getchar();    return 0;}

運行結果

  zmalloc_set_oom_handler

  redisOutOfMemoryHandler----------:10

 

 

現在看看redis的代碼

 

int main(int argc, char **argv) {struct timeval tv;    /* We need to initialize our libraries, and the server configuration. */#ifdef INIT_SETPROCTITLE_REPLACEMENT//初始化參數spt_init(argc, argv);#endifsetlocale(LC_COLLATE,"");/*zmalloc_enable_thread_safeness()開啟了記憶體配置管理的安全執行緒變數,當記憶體配置時,redis會統計一個總記憶體配置量,這是一個共用資源,所以需要原子性操作,在redis的記憶體配置代碼裡,當需要原子操作時,就需要開啟安全執行緒變數。*/zmalloc_enable_thread_safeness();/*zmalloc_set_oom_handler()是一個記憶體配置錯誤處理,當無法得到需要的記憶體量時,會調用redisOutOfMemoryHandler函數。*/    zmalloc_set_oom_handler(redisOutOfMemoryHandler);    srand(time(NULL)^getpid());    gettimeofday(&tv,NULL);    dictSetHashFunctionSeed(tv.tv_sec^tv.tv_usec^getpid());    server.sentinel_mode = checkForSentinelMode(argc,argv);    initServerConfig();    ..........}

  

zmalloc_set_oom_handler註冊回呼函數  
redisOutOfMemoryHandler主要是個log日誌列印,即在記憶體配置失敗的時候觸發回呼函數,列印log。
void *zmalloc(size_t size) {    void *ptr = malloc(size+PREFIX_SIZE);    if (!ptr) zmalloc_oom_handler(size);#ifdef HAVE_MALLOC_SIZE    update_zmalloc_stat_alloc(zmalloc_size(ptr));    return ptr;#else    *((size_t*)ptr) = size;    update_zmalloc_stat_alloc(size+PREFIX_SIZE);    return (char*)ptr+PREFIX_SIZE;#endif}

  在分配記憶體失敗的時候,觸發回呼函數

 

 

三、redis的log日誌

由於redis是單線程的  所以在redis.c裡面的log沒有做成多線程

這樣的log,在單線程下 速度很快,因為無鎖。但是在多線程下是不安全

簡化了下  redis的log  單是大抵就是這樣

#include <stdio.h>#include <stdlib.h>#include <stdarg.h>/* Log levels */#define REDIS_DEBUG 0#define REDIS_VERBOSE 1#define REDIS_NOTICE 2#define REDIS_WARNING 3#define REDIS_MAX_LOGMSG_LEN    1024 /* 預設資訊長度 */void redisLogRaw(int level, const char *msg);void redisLog(int level, const char *fmt, ...);/*verbosity表示開啟log的層級需要寫log的時候,log層級小於等於verbosity寫log否則不會寫log*/struct redisServer {int verbosity;                  /* 記錄層級*/char *logfile;                  /* Path of log file */};struct redisServer server; /* server global state */void redisLog(int level, const char *fmt, ...) {//如果level層級大於verbosity則不列印if (level> server.verbosity) {return;}va_list ap;char msg[REDIS_MAX_LOGMSG_LEN];va_start(ap, fmt);vsnprintf(msg, sizeof(msg), fmt, ap);va_end(ap);redisLogRaw(level,msg);}void redisLogRaw(int level, const char *msg) {#if 1FILE *fp;char buf[64];//int rawmode = (level & REDIS_LOG_RAW);//int log_to_stdout = server.logfile[0] == ‘\0‘;//level &= 0xff; /* clear flags *///if (level < server.verbosity) return;if(server.logfile != NULL){fp=fopen(server.logfile,"a");}else{fp=stdout;}int off;//struct timeval tv;//gettimeofday(&tv,NULL);//off = strftime(buf,sizeof(buf),"%d %b %H:%M:%S.",localtime(&tv.tv_sec));//snprintf(buf+off,sizeof(buf)-off,"%03d",(int)tv.tv_usec/1000);//fprintf(fp,"[%d] %s %c %s\n",(int)getpid(),buf,c[level],msg);fprintf(fp," %s\n",msg);fflush(fp);if(server.logfile != NULL){fclose(fp);}#endif}int main(void){server.verbosity=2;server.logfile=NULL;redisLog(1,"11111111\n");redisLog(2,"22222\n");redisLog(3,"333\n");getchar();return 0;}

  

 

關於log日誌  怎麼在不影響效能的情況下 最快最多的 寫日誌能,

多線程用鎖的話必然會影響速度

用雙隊列這種方式好像挺不錯,可以把log的內容的放到隊列裡,一個隊列負責接收log,一個隊列負責列印log

列印完的log隊列,然後跟接收log隊列互換,在繼續   這種方法陳碩的 《linux多線程網路編程》介紹過   

 

好像Google的glog好像效能不錯,什麼時候有時間把glog看完 再來討論log日誌的實現

 

redis 學習筆記一

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.