找了半天,发觉还是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_SIZEupdate_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多线程网络编程》介绍过

好像谷歌的glog好像性能不错,什么时候有时间把glog看完 再来讨论log日志的实现

转载于:https://www.cnblogs.com/ztteng/p/4039274.html

redis 学习笔记一相关推荐

  1. Redis学习笔记 - 数据类型与API(1)Key

    Redis学习笔记 - 数据类型与API(1)Key Key相关命令 1. 常用命令 命令 含义 时间复杂度 keys 查找所有符合给定模式 pattern 的 key O(N), N 为数据库中 k ...

  2. Redis学习笔记~Redis在windows环境下的安装

    Redis是一个key-value的存储系统,它最大的特点就是可以将数据序列化到文件中. redis存储在服务器的内存或者文件中,它不是session,不是cookies,它只是个更安全,更稳定,更可 ...

  3. redis学习笔记-持久化

    redis学习笔记-持久化 前言 redis持久化有两种方式:RDB和AOF.分别对应着全量复制和增量复制.深刻理解各自的实现方式及适用场景对redis的使用和运维十分重要.下面就分别介绍. RDB持 ...

  4. StackExchange.Redis学习笔记(五) 发布和订阅

    StackExchange.Redis学习笔记(五) 发布和订阅 原文:StackExchange.Redis学习笔记(五) 发布和订阅 Redis命令中的Pub/Sub Redis在 2.0之后的版 ...

  5. Redis学习笔记~分布式的Pub/Sub模式

    redis的客户端有很多,这次用它的pub/sub发布与订阅我选择了StackExchange.Redis,发布与订阅大家应该很清楚了,首先一个订阅者,订阅一个服务,服务执行一些处理程序(可能是写个日 ...

  6. Redis学习笔记——SpringDataRedis的使用

    与Spring集成 我需要哪些jar包? <dependency><groupId>org.springframework.data</groupId><ar ...

  7. Redis学习笔记(五)——持久化及redis.conf配置文件叙述

    对于日常使用来说,学习完SpringBoot集成Redis就够我们工作中使用了,但是既然学习了,我们就学习一些Redis的配置及概念,使我们可以更深层次的理解Redis,以及增强我们的面试成功概率,接 ...

  8. Redis学习笔记1-理论篇

    目录 1,Redis 数据类型的底层结构 1.1,Redis 中的数据类型 1.2,全局哈希表 1.3,数据类型的底层结构 1.4,哈希冲突 1.5,rehash 操作 2,Redis 的 IO 模型 ...

  9. Redis学习笔记(实战篇)(自用)

    Redis学习笔记(实战篇)(自用) 本文根据黑马程序员的课程资料与百度搜索的资料共同整理所得,仅用于学习使用,如有侵权,请联系删除 文章目录 Redis学习笔记(实战篇)(自用) 1.基于Sessi ...

  10. Redis学习笔记(B站狂神说)(自己总结方便复习)

    Redis学习笔记B站狂神说 redis: 非关系型数据库 一.NoSQL概述 1.为什么要用Nosql 1.单机Mysql的年代 思考一下,这种情况下:整个网站的瓶颈是什么? 1.数据量如果太大,一 ...

最新文章

  1. ICCV 2019 | 无需数据集的Student Networks
  2. each 数据获取attr_调用高德POI数据,带你玩转长沙
  3. 纯正价格正则表达式,请指正
  4. Python HTMLCalendar类| 带实例的formatyear()方法
  5. boost signal2 trackable
  6. O036、Snapshot Instance 操作详解
  7. SoX-linux里操作音频的瑞士×××
  8. Bailian4144 畜栏保留问题【贪心】
  9. Java Interview Questions (1)
  10. 酷比魔方iplay20_799元买国产“山寨板”是否值得?酷比魔方iPlay20 Pro评测
  11. 运维工程师平均月工资是多少?
  12. Windows系统开机自动运行程序和自动启动服务
  13. FogROS2 使用 ROS 2 的云和雾机器人的自适应和可扩展平台
  14. python中的yield是什么意思_python中yield指的什么意思
  15. 云MAS - MT-提交状态码
  16. 人类高质量程序员电脑配置(持续更新)
  17. 解决Google浏览器首页被2345网站劫持
  18. javaScript+css+html——键盘事件(通过键盘上下左右控制图形位置)
  19. Apache的OpenOffice
  20. 如何进入mysql数据库

热门文章

  1. 查看Linux服务器运行级别命令,linux命令1、如何查看当前的Linux服务器的运行级别?...
  2. vs2017python开发_VS2017作为python开发的IDE
  3. JavaWeb之Cookie,Session
  4. php 关闭电脑,php实现用手机关闭计算机(电脑)的方法
  5. 创建链表和遍历链表算法演示
  6. HDFS SnapShot原理
  7. 互联网晚报 | 2月25日 星期五 | 元宇宙概念,热度显著下降;​腾讯正洽谈落地“东数西算”大湾区枢纽韶关数据中心集群...
  8. 链计算:构建信任网络,致力无边界协同
  9. 一道滴滴的产品面试题
  10. 2021年中国电竞运动行业发展报告