设为首页 收藏本站
查看: 1000|回复: 0

[经验分享] redis 学习笔记一

[复制链接]
发表于 2015-7-19 12:41:21 | 显示全部楼层 |阅读模式
  找了半天,发觉还是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
#include

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);
#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没有做成多线程
  这样的log,在单线程下 速度很快,因为无锁。但是在多线程下是不安全
  简化了下  redis的log  单是大抵就是这样



#include
#include
#include
/* 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\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多线程网络编程》介绍过   
  
  好像谷歌的glog好像性能不错,什么时候有时间把glog看完 再来讨论log日志的实现
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-88277-1-1.html 上篇帖子: 二.redis 数据类型 下篇帖子: session放入缓存(redis)、DB
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表