redis学習ノート1

5763 ワード

長い間探していたが、やはりredisのソースコードが楽に見えることに気づいた.だから今年はredisのソースを読んでついでに読書ノートを作ることにしました.ちゃんと記録しておきます.でも今は頭で物を記録するのが嫌になり、noteで覚えるのが好きになりました.っていうか、そんなに頭を使わないと早すぎる認知症にならないかな~~~
 
一、redisダウンロードコンパイル
ここには何も言うことはない.
使用するバージョンはredis-2.8.17です
 
1)redis-serverは実行可能プログラム
2)mian関数はredis.c奥
3)srcディレクトリの下でデバッグを変更する場合、makeまたはmake cleanを変更します.makeでいい
 
main関数から言えばここで2つの部分を先に言います1つはredisの中のコールバック関数でもう1つはredisの中のlogログです
二、redis内のコールバック関数
まずコードを見てください.これはredisの中のコールバック関数を出して修正します
/*

redis      

*/

#include<stdio.h>

#include<stdlib.h>

 

 

static void zmalloc_default_oom(size_t size) 

{

    printf("zmalloc_default_oom
"); fprintf(stderr, "zmalloc: Out of memory trying to allocate %d bytes
",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
"); zmalloc_oom_handler = oom_handler; } void redisOutOfMemoryHandler(size_t allocation_size) { printf("redisOutOfMemoryHandler------:%d
",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);

#endif

	setlocale(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は、ロックがないため、単一スレッドでは速度が速い.しかし、マルチスレッドでは安全ではありません.
下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 1

	

	FILE *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
",(int)getpid(),buf,c[level],msg); fprintf(fp," %s
",msg); fflush(fp); if(server.logfile != NULL) { fclose(fp); } #endif } int main(void) { server.verbosity=2; server.logfile=NULL; redisLog(1,"11111111
"); redisLog(2,"22222
"); redisLog(3,"333
"); getchar(); return 0; }

  
 
logログがパフォーマンスに影響を及ぼさずに最も速く最も多くのログを書くことができるかについて、
マルチスレッド用ロックは必然的に速度に影響します
ダブルキューを使うのはいいようですが、logの内容をキューに入れることができます.1つのキューはlogを受信し、1つのキューはlogを印刷します.
印刷されたlogキューを受信したlogキューと交換し、この方法を継続する陳碩の「linuxマルチスレッドネットワークプログラミング」で紹介した.
 
Googleのglogは性能が良いようで、いつglogを見終わってからlogログの実現を討論する時間があります